import pyloxi @ 56db3af912fd38fe3789e7629a823788b94f463d
diff --git a/src/python/loxi/__init__.py b/src/python/loxi/__init__.py
index 9fcc9bf..58fa3d7 100644
--- a/src/python/loxi/__init__.py
+++ b/src/python/loxi/__init__.py
@@ -1,21 +1,12 @@
-#
-# Copyright 2012, 2013, Big Switch Networks, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
 
 # Automatically generated by LOXI from template toplevel_init.py
 # Do not modify
 
+version_names = {1: '1.0', 2: '1.1', 3: '1.2', 4: '1.3'}
+
 def protocol(ver):
     """
     Import and return the protocol module for the given wire version.
@@ -23,6 +14,15 @@
     if ver == 1:
         import of10
         return of10
+    elif ver == 2:
+        import of11
+        return of11
+    elif ver == 3:
+        import of12
+        return of12
+    elif ver == 4:
+        import of13
+        return of13
     else:
         raise ValueError
 
@@ -31,3 +31,12 @@
     Raised when failing to deserialize an invalid OpenFlow message.
     """
     pass
+
+class Unimplemented(Exception):
+    """
+    Raised when an OpenFlow feature is not yet implemented in PyLoxi.
+    """
+    pass
+
+def unimplemented(msg):
+    raise Unimplemented(msg)
diff --git a/src/python/loxi/of10/__init__.py b/src/python/loxi/of10/__init__.py
index 9b3bf53..6f2680d 100644
--- a/src/python/loxi/of10/__init__.py
+++ b/src/python/loxi/of10/__init__.py
@@ -1,17 +1,6 @@
-#
-# Copyright 2012, 2013, Big Switch Networks, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
 
 # Automatically generated by LOXI from template init.py
 # Do not modify
diff --git a/src/python/loxi/of10/action.py b/src/python/loxi/of10/action.py
index c6129a5..8fe2997 100644
--- a/src/python/loxi/of10/action.py
+++ b/src/python/loxi/of10/action.py
@@ -1,17 +1,6 @@
-#
-# Copyright 2012, 2013, Big Switch Networks, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
 
 # Automatically generated by LOXI from template action.py
 # Do not modify
@@ -19,22 +8,15 @@
 import struct
 import const
 import util
+import loxi.generic_util
 import loxi
 
-def unpack_list(buf):
-    if len(buf) % 8 != 0: raise loxi.ProtocolError("action list length not a multiple of 8")
-    actions = []
-    offset = 0
-    while offset < len(buf):
-        type, length = struct.unpack_from("!HH", buf, offset)
-        if length == 0: raise loxi.ProtocolError("action length is 0")
-        if length % 8 != 0: raise loxi.ProtocolError("action length not a multiple of 8")
-        if offset + length > len(buf): raise loxi.ProtocolError("action length overruns list length")
-        parser = parsers.get(type)
-        if not parser: raise loxi.ProtocolError("unknown action type %d" % type)
-        actions.append(parser(buffer(buf, offset, length)))
-        offset += length
-    return actions
+def unpack_list(reader):
+    def deserializer(reader, typ):
+        parser = parsers.get(typ)
+        if not parser: raise loxi.ProtocolError("unknown action type %d" % typ)
+        return parser(reader)
+    return loxi.generic_util.unpack_list_tlv16(reader, deserializer)
 
 class Action(object):
     type = None # override in subclass
@@ -45,7 +27,7 @@
     experimenter = 0x5c16c7
     subtype = 1
 
-    def __init__(self, dest_port=None, vlan_tag=None, copy_stage=None, pad=None):
+    def __init__(self, dest_port=None, vlan_tag=None, copy_stage=None):
         if dest_port != None:
             self.dest_port = dest_port
         else:
@@ -58,10 +40,7 @@
             self.copy_stage = copy_stage
         else:
             self.copy_stage = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0,0]
+        return
 
     def pack(self):
         packed = []
@@ -72,7 +51,7 @@
         packed.append(struct.pack("!L", self.dest_port))
         packed.append(struct.pack("!L", self.vlan_tag))
         packed.append(struct.pack("!B", self.copy_stage))
-        packed.append(struct.pack("!3B", *self.pad))
+        packed.append('\x00' * 3)
         length = sum([len(x) for x in packed])
         packed[1] = struct.pack("!H", length)
         return ''.join(packed)
@@ -80,28 +59,28 @@
     @staticmethod
     def unpack(buf):
         obj = bsn_mirror()
-        type = struct.unpack_from('!H', buf, 0)[0]
-        assert(type == const.OFPAT_VENDOR)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 24: raise loxi.ProtocolError("bsn_mirror length is %d, should be 24" % _length)
-        experimenter = struct.unpack_from('!L', buf, 4)[0]
-        assert(experimenter == 0x5c16c7)
-        subtype = struct.unpack_from('!L', buf, 8)[0]
-        assert(subtype == 1)
-        obj.dest_port = struct.unpack_from('!L', buf, 12)[0]
-        obj.vlan_tag = struct.unpack_from('!L', buf, 16)[0]
-        obj.copy_stage = struct.unpack_from('!B', buf, 20)[0]
-        obj.pad = list(struct.unpack_from('!3B', buf, 21))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_VENDOR)
+        _len = reader.read('!H')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 1)
+        obj.dest_port = reader.read('!L')[0]
+        obj.vlan_tag = reader.read('!L')[0]
+        obj.copy_stage = reader.read('!B')[0]
+        reader.skip(3)
         return obj
 
     def __eq__(self, other):
         if type(self) != type(other): return False
-        if self.type != other.type: return False
         if self.dest_port != other.dest_port: return False
         if self.vlan_tag != other.vlan_tag: return False
         if self.copy_stage != other.copy_stage: return False
-        if self.pad != other.pad: return False
         return True
 
     def __ne__(self, other):
@@ -124,9 +103,6 @@
                 q.text(","); q.breakable()
                 q.text("copy_stage = ");
                 q.text("%#x" % self.copy_stage)
-                q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
             q.breakable()
         q.text('}')
 
@@ -140,6 +116,7 @@
             self.dst = dst
         else:
             self.dst = 0
+        return
 
     def pack(self):
         packed = []
@@ -155,21 +132,22 @@
     @staticmethod
     def unpack(buf):
         obj = bsn_set_tunnel_dst()
-        type = struct.unpack_from('!H', buf, 0)[0]
-        assert(type == const.OFPAT_VENDOR)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 16: raise loxi.ProtocolError("bsn_set_tunnel_dst length is %d, should be 16" % _length)
-        experimenter = struct.unpack_from('!L', buf, 4)[0]
-        assert(experimenter == 0x5c16c7)
-        subtype = struct.unpack_from('!L', buf, 8)[0]
-        assert(subtype == 2)
-        obj.dst = struct.unpack_from('!L', buf, 12)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_VENDOR)
+        _len = reader.read('!H')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 2)
+        obj.dst = reader.read('!L')[0]
         return obj
 
     def __eq__(self, other):
         if type(self) != type(other): return False
-        if self.type != other.type: return False
         if self.dst != other.dst: return False
         return True
 
@@ -193,26 +171,23 @@
 class enqueue(Action):
     type = const.OFPAT_ENQUEUE
 
-    def __init__(self, port=None, pad=None, queue_id=None):
+    def __init__(self, port=None, queue_id=None):
         if port != None:
             self.port = port
         else:
             self.port = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0,0,0,0,0]
         if queue_id != None:
             self.queue_id = queue_id
         else:
             self.queue_id = 0
+        return
 
     def pack(self):
         packed = []
         packed.append(struct.pack("!H", self.type))
         packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
         packed.append(struct.pack("!H", self.port))
-        packed.append(struct.pack("!6B", *self.pad))
+        packed.append('\x00' * 6)
         packed.append(struct.pack("!L", self.queue_id))
         length = sum([len(x) for x in packed])
         packed[1] = struct.pack("!H", length)
@@ -221,21 +196,21 @@
     @staticmethod
     def unpack(buf):
         obj = enqueue()
-        type = struct.unpack_from('!H', buf, 0)[0]
-        assert(type == const.OFPAT_ENQUEUE)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 16: raise loxi.ProtocolError("enqueue length is %d, should be 16" % _length)
-        obj.port = struct.unpack_from('!H', buf, 4)[0]
-        obj.pad = list(struct.unpack_from('!6B', buf, 6))
-        obj.queue_id = struct.unpack_from('!L', buf, 12)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_ENQUEUE)
+        _len = reader.read('!H')[0]
+        obj.port = reader.read('!H')[0]
+        reader.skip(6)
+        obj.queue_id = reader.read('!L')[0]
         return obj
 
     def __eq__(self, other):
         if type(self) != type(other): return False
-        if self.type != other.type: return False
         if self.port != other.port: return False
-        if self.pad != other.pad: return False
         if self.queue_id != other.queue_id: return False
         return True
 
@@ -254,9 +229,6 @@
                 q.text("port = ");
                 q.text(util.pretty_port(self.port))
                 q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
-                q.text(","); q.breakable()
                 q.text("queue_id = ");
                 q.text("%#x" % self.queue_id)
             q.breakable()
@@ -267,15 +239,8 @@
     experimenter = 0x2320
     subtype = 18
 
-    def __init__(self, pad=None, pad2=None):
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = 0
-        if pad2 != None:
-            self.pad2 = pad2
-        else:
-            self.pad2 = 0
+    def __init__(self):
+        return
 
     def pack(self):
         packed = []
@@ -283,8 +248,8 @@
         packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
         packed.append(struct.pack("!L", self.experimenter))
         packed.append(struct.pack("!H", self.subtype))
-        packed.append(struct.pack("!H", self.pad))
-        packed.append(struct.pack("!L", self.pad2))
+        packed.append('\x00' * 2)
+        packed.append('\x00' * 4)
         length = sum([len(x) for x in packed])
         packed[1] = struct.pack("!H", length)
         return ''.join(packed)
@@ -292,24 +257,23 @@
     @staticmethod
     def unpack(buf):
         obj = nicira_dec_ttl()
-        type = struct.unpack_from('!H', buf, 0)[0]
-        assert(type == const.OFPAT_VENDOR)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 16: raise loxi.ProtocolError("nicira_dec_ttl length is %d, should be 16" % _length)
-        experimenter = struct.unpack_from('!L', buf, 4)[0]
-        assert(experimenter == 0x2320)
-        subtype = struct.unpack_from('!H', buf, 8)[0]
-        assert(subtype == 18)
-        obj.pad = struct.unpack_from('!H', buf, 10)[0]
-        obj.pad2 = struct.unpack_from('!L', buf, 12)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_VENDOR)
+        _len = reader.read('!H')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x2320)
+        _subtype = reader.read('!H')[0]
+        assert(_subtype == 18)
+        reader.skip(2)
+        reader.skip(4)
         return obj
 
     def __eq__(self, other):
         if type(self) != type(other): return False
-        if self.type != other.type: return False
-        if self.pad != other.pad: return False
-        if self.pad2 != other.pad2: return False
         return True
 
     def __ne__(self, other):
@@ -324,11 +288,6 @@
         with q.group():
             with q.indent(2):
                 q.breakable()
-                q.text("pad = ");
-                q.text("%#x" % self.pad)
-                q.text(","); q.breakable()
-                q.text("pad2 = ");
-                q.text("%#x" % self.pad2)
             q.breakable()
         q.text('}')
 
@@ -344,6 +303,7 @@
             self.max_len = max_len
         else:
             self.max_len = 0
+        return
 
     def pack(self):
         packed = []
@@ -358,18 +318,19 @@
     @staticmethod
     def unpack(buf):
         obj = output()
-        type = struct.unpack_from('!H', buf, 0)[0]
-        assert(type == const.OFPAT_OUTPUT)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 8: raise loxi.ProtocolError("output length is %d, should be 8" % _length)
-        obj.port = struct.unpack_from('!H', buf, 4)[0]
-        obj.max_len = struct.unpack_from('!H', buf, 6)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_OUTPUT)
+        _len = reader.read('!H')[0]
+        obj.port = reader.read('!H')[0]
+        obj.max_len = reader.read('!H')[0]
         return obj
 
     def __eq__(self, other):
         if type(self) != type(other): return False
-        if self.type != other.type: return False
         if self.port != other.port: return False
         if self.max_len != other.max_len: return False
         return True
@@ -397,22 +358,19 @@
 class set_dl_dst(Action):
     type = const.OFPAT_SET_DL_DST
 
-    def __init__(self, dl_addr=None, pad=None):
+    def __init__(self, dl_addr=None):
         if dl_addr != None:
             self.dl_addr = dl_addr
         else:
             self.dl_addr = [0,0,0,0,0,0]
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0,0,0,0,0]
+        return
 
     def pack(self):
         packed = []
         packed.append(struct.pack("!H", self.type))
         packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
         packed.append(struct.pack("!6B", *self.dl_addr))
-        packed.append(struct.pack("!6B", *self.pad))
+        packed.append('\x00' * 6)
         length = sum([len(x) for x in packed])
         packed[1] = struct.pack("!H", length)
         return ''.join(packed)
@@ -420,20 +378,20 @@
     @staticmethod
     def unpack(buf):
         obj = set_dl_dst()
-        type = struct.unpack_from('!H', buf, 0)[0]
-        assert(type == const.OFPAT_SET_DL_DST)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 16: raise loxi.ProtocolError("set_dl_dst length is %d, should be 16" % _length)
-        obj.dl_addr = list(struct.unpack_from('!6B', buf, 4))
-        obj.pad = list(struct.unpack_from('!6B', buf, 10))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_DL_DST)
+        _len = reader.read('!H')[0]
+        obj.dl_addr = list(reader.read('!6B'))
+        reader.skip(6)
         return obj
 
     def __eq__(self, other):
         if type(self) != type(other): return False
-        if self.type != other.type: return False
         if self.dl_addr != other.dl_addr: return False
-        if self.pad != other.pad: return False
         return True
 
     def __ne__(self, other):
@@ -450,31 +408,25 @@
                 q.breakable()
                 q.text("dl_addr = ");
                 q.text(util.pretty_mac(self.dl_addr))
-                q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
             q.breakable()
         q.text('}')
 
 class set_dl_src(Action):
     type = const.OFPAT_SET_DL_SRC
 
-    def __init__(self, dl_addr=None, pad=None):
+    def __init__(self, dl_addr=None):
         if dl_addr != None:
             self.dl_addr = dl_addr
         else:
             self.dl_addr = [0,0,0,0,0,0]
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0,0,0,0,0]
+        return
 
     def pack(self):
         packed = []
         packed.append(struct.pack("!H", self.type))
         packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
         packed.append(struct.pack("!6B", *self.dl_addr))
-        packed.append(struct.pack("!6B", *self.pad))
+        packed.append('\x00' * 6)
         length = sum([len(x) for x in packed])
         packed[1] = struct.pack("!H", length)
         return ''.join(packed)
@@ -482,20 +434,20 @@
     @staticmethod
     def unpack(buf):
         obj = set_dl_src()
-        type = struct.unpack_from('!H', buf, 0)[0]
-        assert(type == const.OFPAT_SET_DL_SRC)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 16: raise loxi.ProtocolError("set_dl_src length is %d, should be 16" % _length)
-        obj.dl_addr = list(struct.unpack_from('!6B', buf, 4))
-        obj.pad = list(struct.unpack_from('!6B', buf, 10))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_DL_SRC)
+        _len = reader.read('!H')[0]
+        obj.dl_addr = list(reader.read('!6B'))
+        reader.skip(6)
         return obj
 
     def __eq__(self, other):
         if type(self) != type(other): return False
-        if self.type != other.type: return False
         if self.dl_addr != other.dl_addr: return False
-        if self.pad != other.pad: return False
         return True
 
     def __ne__(self, other):
@@ -512,9 +464,6 @@
                 q.breakable()
                 q.text("dl_addr = ");
                 q.text(util.pretty_mac(self.dl_addr))
-                q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
             q.breakable()
         q.text('}')
 
@@ -526,6 +475,7 @@
             self.nw_addr = nw_addr
         else:
             self.nw_addr = 0
+        return
 
     def pack(self):
         packed = []
@@ -539,17 +489,18 @@
     @staticmethod
     def unpack(buf):
         obj = set_nw_dst()
-        type = struct.unpack_from('!H', buf, 0)[0]
-        assert(type == const.OFPAT_SET_NW_DST)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 8: raise loxi.ProtocolError("set_nw_dst length is %d, should be 8" % _length)
-        obj.nw_addr = struct.unpack_from('!L', buf, 4)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_NW_DST)
+        _len = reader.read('!H')[0]
+        obj.nw_addr = reader.read('!L')[0]
         return obj
 
     def __eq__(self, other):
         if type(self) != type(other): return False
-        if self.type != other.type: return False
         if self.nw_addr != other.nw_addr: return False
         return True
 
@@ -578,6 +529,7 @@
             self.nw_addr = nw_addr
         else:
             self.nw_addr = 0
+        return
 
     def pack(self):
         packed = []
@@ -591,17 +543,18 @@
     @staticmethod
     def unpack(buf):
         obj = set_nw_src()
-        type = struct.unpack_from('!H', buf, 0)[0]
-        assert(type == const.OFPAT_SET_NW_SRC)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 8: raise loxi.ProtocolError("set_nw_src length is %d, should be 8" % _length)
-        obj.nw_addr = struct.unpack_from('!L', buf, 4)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_NW_SRC)
+        _len = reader.read('!H')[0]
+        obj.nw_addr = reader.read('!L')[0]
         return obj
 
     def __eq__(self, other):
         if type(self) != type(other): return False
-        if self.type != other.type: return False
         if self.nw_addr != other.nw_addr: return False
         return True
 
@@ -625,22 +578,19 @@
 class set_nw_tos(Action):
     type = const.OFPAT_SET_NW_TOS
 
-    def __init__(self, nw_tos=None, pad=None):
+    def __init__(self, nw_tos=None):
         if nw_tos != None:
             self.nw_tos = nw_tos
         else:
             self.nw_tos = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0,0]
+        return
 
     def pack(self):
         packed = []
         packed.append(struct.pack("!H", self.type))
         packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
         packed.append(struct.pack("!B", self.nw_tos))
-        packed.append(struct.pack("!3B", *self.pad))
+        packed.append('\x00' * 3)
         length = sum([len(x) for x in packed])
         packed[1] = struct.pack("!H", length)
         return ''.join(packed)
@@ -648,20 +598,20 @@
     @staticmethod
     def unpack(buf):
         obj = set_nw_tos()
-        type = struct.unpack_from('!H', buf, 0)[0]
-        assert(type == const.OFPAT_SET_NW_TOS)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 8: raise loxi.ProtocolError("set_nw_tos length is %d, should be 8" % _length)
-        obj.nw_tos = struct.unpack_from('!B', buf, 4)[0]
-        obj.pad = list(struct.unpack_from('!3B', buf, 5))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_NW_TOS)
+        _len = reader.read('!H')[0]
+        obj.nw_tos = reader.read('!B')[0]
+        reader.skip(3)
         return obj
 
     def __eq__(self, other):
         if type(self) != type(other): return False
-        if self.type != other.type: return False
         if self.nw_tos != other.nw_tos: return False
-        if self.pad != other.pad: return False
         return True
 
     def __ne__(self, other):
@@ -678,31 +628,25 @@
                 q.breakable()
                 q.text("nw_tos = ");
                 q.text("%#x" % self.nw_tos)
-                q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
             q.breakable()
         q.text('}')
 
 class set_tp_dst(Action):
     type = const.OFPAT_SET_TP_DST
 
-    def __init__(self, tp_port=None, pad=None):
+    def __init__(self, tp_port=None):
         if tp_port != None:
             self.tp_port = tp_port
         else:
             self.tp_port = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0]
+        return
 
     def pack(self):
         packed = []
         packed.append(struct.pack("!H", self.type))
         packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
         packed.append(struct.pack("!H", self.tp_port))
-        packed.append(struct.pack("!2B", *self.pad))
+        packed.append('\x00' * 2)
         length = sum([len(x) for x in packed])
         packed[1] = struct.pack("!H", length)
         return ''.join(packed)
@@ -710,20 +654,20 @@
     @staticmethod
     def unpack(buf):
         obj = set_tp_dst()
-        type = struct.unpack_from('!H', buf, 0)[0]
-        assert(type == const.OFPAT_SET_TP_DST)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 8: raise loxi.ProtocolError("set_tp_dst length is %d, should be 8" % _length)
-        obj.tp_port = struct.unpack_from('!H', buf, 4)[0]
-        obj.pad = list(struct.unpack_from('!2B', buf, 6))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_TP_DST)
+        _len = reader.read('!H')[0]
+        obj.tp_port = reader.read('!H')[0]
+        reader.skip(2)
         return obj
 
     def __eq__(self, other):
         if type(self) != type(other): return False
-        if self.type != other.type: return False
         if self.tp_port != other.tp_port: return False
-        if self.pad != other.pad: return False
         return True
 
     def __ne__(self, other):
@@ -740,31 +684,25 @@
                 q.breakable()
                 q.text("tp_port = ");
                 q.text("%#x" % self.tp_port)
-                q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
             q.breakable()
         q.text('}')
 
 class set_tp_src(Action):
     type = const.OFPAT_SET_TP_SRC
 
-    def __init__(self, tp_port=None, pad=None):
+    def __init__(self, tp_port=None):
         if tp_port != None:
             self.tp_port = tp_port
         else:
             self.tp_port = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0]
+        return
 
     def pack(self):
         packed = []
         packed.append(struct.pack("!H", self.type))
         packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
         packed.append(struct.pack("!H", self.tp_port))
-        packed.append(struct.pack("!2B", *self.pad))
+        packed.append('\x00' * 2)
         length = sum([len(x) for x in packed])
         packed[1] = struct.pack("!H", length)
         return ''.join(packed)
@@ -772,20 +710,20 @@
     @staticmethod
     def unpack(buf):
         obj = set_tp_src()
-        type = struct.unpack_from('!H', buf, 0)[0]
-        assert(type == const.OFPAT_SET_TP_SRC)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 8: raise loxi.ProtocolError("set_tp_src length is %d, should be 8" % _length)
-        obj.tp_port = struct.unpack_from('!H', buf, 4)[0]
-        obj.pad = list(struct.unpack_from('!2B', buf, 6))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_TP_SRC)
+        _len = reader.read('!H')[0]
+        obj.tp_port = reader.read('!H')[0]
+        reader.skip(2)
         return obj
 
     def __eq__(self, other):
         if type(self) != type(other): return False
-        if self.type != other.type: return False
         if self.tp_port != other.tp_port: return False
-        if self.pad != other.pad: return False
         return True
 
     def __ne__(self, other):
@@ -802,31 +740,25 @@
                 q.breakable()
                 q.text("tp_port = ");
                 q.text("%#x" % self.tp_port)
-                q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
             q.breakable()
         q.text('}')
 
 class set_vlan_pcp(Action):
     type = const.OFPAT_SET_VLAN_PCP
 
-    def __init__(self, vlan_pcp=None, pad=None):
+    def __init__(self, vlan_pcp=None):
         if vlan_pcp != None:
             self.vlan_pcp = vlan_pcp
         else:
             self.vlan_pcp = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0,0]
+        return
 
     def pack(self):
         packed = []
         packed.append(struct.pack("!H", self.type))
         packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
         packed.append(struct.pack("!B", self.vlan_pcp))
-        packed.append(struct.pack("!3B", *self.pad))
+        packed.append('\x00' * 3)
         length = sum([len(x) for x in packed])
         packed[1] = struct.pack("!H", length)
         return ''.join(packed)
@@ -834,20 +766,20 @@
     @staticmethod
     def unpack(buf):
         obj = set_vlan_pcp()
-        type = struct.unpack_from('!H', buf, 0)[0]
-        assert(type == const.OFPAT_SET_VLAN_PCP)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 8: raise loxi.ProtocolError("set_vlan_pcp length is %d, should be 8" % _length)
-        obj.vlan_pcp = struct.unpack_from('!B', buf, 4)[0]
-        obj.pad = list(struct.unpack_from('!3B', buf, 5))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_VLAN_PCP)
+        _len = reader.read('!H')[0]
+        obj.vlan_pcp = reader.read('!B')[0]
+        reader.skip(3)
         return obj
 
     def __eq__(self, other):
         if type(self) != type(other): return False
-        if self.type != other.type: return False
         if self.vlan_pcp != other.vlan_pcp: return False
-        if self.pad != other.pad: return False
         return True
 
     def __ne__(self, other):
@@ -864,31 +796,25 @@
                 q.breakable()
                 q.text("vlan_pcp = ");
                 q.text("%#x" % self.vlan_pcp)
-                q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
             q.breakable()
         q.text('}')
 
 class set_vlan_vid(Action):
     type = const.OFPAT_SET_VLAN_VID
 
-    def __init__(self, vlan_vid=None, pad=None):
+    def __init__(self, vlan_vid=None):
         if vlan_vid != None:
             self.vlan_vid = vlan_vid
         else:
             self.vlan_vid = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0]
+        return
 
     def pack(self):
         packed = []
         packed.append(struct.pack("!H", self.type))
         packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
         packed.append(struct.pack("!H", self.vlan_vid))
-        packed.append(struct.pack("!2B", *self.pad))
+        packed.append('\x00' * 2)
         length = sum([len(x) for x in packed])
         packed[1] = struct.pack("!H", length)
         return ''.join(packed)
@@ -896,20 +822,20 @@
     @staticmethod
     def unpack(buf):
         obj = set_vlan_vid()
-        type = struct.unpack_from('!H', buf, 0)[0]
-        assert(type == const.OFPAT_SET_VLAN_VID)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 8: raise loxi.ProtocolError("set_vlan_vid length is %d, should be 8" % _length)
-        obj.vlan_vid = struct.unpack_from('!H', buf, 4)[0]
-        obj.pad = list(struct.unpack_from('!2B', buf, 6))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_VLAN_VID)
+        _len = reader.read('!H')[0]
+        obj.vlan_vid = reader.read('!H')[0]
+        reader.skip(2)
         return obj
 
     def __eq__(self, other):
         if type(self) != type(other): return False
-        if self.type != other.type: return False
         if self.vlan_vid != other.vlan_vid: return False
-        if self.pad != other.pad: return False
         return True
 
     def __ne__(self, other):
@@ -926,26 +852,20 @@
                 q.breakable()
                 q.text("vlan_vid = ");
                 q.text("%#x" % self.vlan_vid)
-                q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
             q.breakable()
         q.text('}')
 
 class strip_vlan(Action):
     type = const.OFPAT_STRIP_VLAN
 
-    def __init__(self, pad=None):
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0,0,0]
+    def __init__(self):
+        return
 
     def pack(self):
         packed = []
         packed.append(struct.pack("!H", self.type))
         packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
-        packed.append(struct.pack("!4B", *self.pad))
+        packed.append('\x00' * 4)
         length = sum([len(x) for x in packed])
         packed[1] = struct.pack("!H", length)
         return ''.join(packed)
@@ -953,18 +873,18 @@
     @staticmethod
     def unpack(buf):
         obj = strip_vlan()
-        type = struct.unpack_from('!H', buf, 0)[0]
-        assert(type == const.OFPAT_STRIP_VLAN)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 8: raise loxi.ProtocolError("strip_vlan length is %d, should be 8" % _length)
-        obj.pad = list(struct.unpack_from('!4B', buf, 4))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_STRIP_VLAN)
+        _len = reader.read('!H')[0]
+        reader.skip(4)
         return obj
 
     def __eq__(self, other):
         if type(self) != type(other): return False
-        if self.type != other.type: return False
-        if self.pad != other.pad: return False
         return True
 
     def __ne__(self, other):
@@ -979,26 +899,22 @@
         with q.group():
             with q.indent(2):
                 q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
             q.breakable()
         q.text('}')
 
 
-def parse_vendor(buf):
-    if len(buf) < 16:
-        raise loxi.ProtocolError("experimenter action too short")
+def parse_vendor(reader):
 
-    experimenter, = struct.unpack_from("!L", buf, 4)
+    experimenter, = reader.peek("!4xL")
     if experimenter == 0x005c16c7: # Big Switch Networks
-        subtype, = struct.unpack_from("!L", buf, 8)
+        subtype, = reader.peek("!8xL")
     elif experimenter == 0x00002320: # Nicira
-        subtype, = struct.unpack_from("!H", buf, 8)
+        subtype, = reader.peek("!8xH")
     else:
         raise loxi.ProtocolError("unexpected experimenter id %#x" % experimenter)
 
     if subtype in experimenter_parsers[experimenter]:
-        return experimenter_parsers[experimenter][subtype](buf)
+        return experimenter_parsers[experimenter][subtype](reader)
     else:
         raise loxi.ProtocolError("unexpected BSN experimenter subtype %#x" % subtype)
 
diff --git a/src/python/loxi/of10/common.py b/src/python/loxi/of10/common.py
index 07c41d0..cfee494 100644
--- a/src/python/loxi/of10/common.py
+++ b/src/python/loxi/of10/common.py
@@ -1,17 +1,6 @@
-#
-# Copyright 2012, 2013, Big Switch Networks, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
 
 # Automatically generated by LOXI from template common.py
 # Do not modify
@@ -21,58 +10,59 @@
 import action
 import const
 import util
+import loxi.generic_util
+
 
 # HACK make this module visible as 'common' to simplify code generation
 common = sys.modules[__name__]
 
-def unpack_list_flow_stats_entry(buf):
-    entries = []
-    offset = 0
-    while offset < len(buf):
-        length, = struct.unpack_from("!H", buf, offset)
-        if length == 0: raise loxi.ProtocolError("entry length is 0")
-        if offset + length > len(buf): raise loxi.ProtocolError("entry length overruns list length")
-        entries.append(flow_stats_entry.unpack(buffer(buf, offset, length)))
-        offset += length
-    return entries
+def unpack_list_flow_stats_entry(reader):
+    return loxi.generic_util.unpack_list_lv16(reader, flow_stats_entry.unpack)
 
-def unpack_list_queue_prop(buf):
-    entries = []
-    offset = 0
-    while offset < len(buf):
-        type, length, = struct.unpack_from("!HH", buf, offset)
-        if length == 0: raise loxi.ProtocolError("entry length is 0")
-        if offset + length > len(buf): raise loxi.ProtocolError("entry length overruns list length")
-        if type == const.OFPQT_MIN_RATE:
-            entry = queue_prop_min_rate.unpack(buffer(buf, offset, length))
+def unpack_list_queue_prop(reader):
+    def deserializer(reader, typ):
+        if typ == const.OFPQT_MIN_RATE:
+            return queue_prop_min_rate.unpack(reader)
         else:
-            raise loxi.ProtocolError("unknown queue prop %d" % type)
-        entries.append(entry)
-        offset += length
-    return entries
+            raise loxi.ProtocolError("unknown queue prop %d" % typ)
+    return loxi.generic_util.unpack_list_tlv16(reader, deserializer)
 
-def unpack_list_packet_queue(buf):
-    entries = []
-    offset = 0
-    while offset < len(buf):
-        _, length, = struct.unpack_from("!LH", buf, offset)
-        if length == 0: raise loxi.ProtocolError("entry length is 0")
-        if offset + length > len(buf): raise loxi.ProtocolError("entry length overruns list length")
-        entries.append(packet_queue.unpack(buffer(buf, offset, length)))
-        offset += length
-    return entries
+def unpack_list_packet_queue(reader):
+    def wrapper(reader):
+        length, = reader.peek('!4xH')
+        return packet_queue.unpack(reader.slice(length))
+    return loxi.generic_util.unpack_list(reader, wrapper)
+
+def unpack_list_hello_elem(reader):
+    def deserializer(reader, typ):
+        if typ == const.OFPHET_VERSIONBITMAP:
+            return hello_elem_versionbitmap.unpack(reader)
+        else:
+            return None
+    return [x for x in loxi.generic_util.unpack_list_tlv16(reader, deserializer) if x != None]
+
+def unpack_list_bucket(reader):
+    return loxi.generic_util.unpack_list_lv16(reader, bucket.unpack)
+
+def unpack_list_group_desc_stats_entry(reader):
+    return loxi.generic_util.unpack_list_lv16(reader, group_desc_stats_entry.unpack)
+
+def unpack_list_group_stats_entry(reader):
+    return loxi.generic_util.unpack_list_lv16(reader, group_stats_entry.unpack)
+
+def unpack_list_meter_stats(reader):
+    def wrapper(reader):
+        length, = reader.peek('!4xH')
+        return meter_stats.unpack(reader.slice(length))
+    return loxi.generic_util.unpack_list(reader, wrapper)
 
 class bsn_interface(object):
 
-    def __init__(self, hw_addr=None, pad=None, name=None, ipv4_addr=None, ipv4_netmask=None):
+    def __init__(self, hw_addr=None, name=None, ipv4_addr=None, ipv4_netmask=None):
         if hw_addr != None:
             self.hw_addr = hw_addr
         else:
             self.hw_addr = [0,0,0,0,0,0]
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = 0
         if name != None:
             self.name = name
         else:
@@ -85,11 +75,12 @@
             self.ipv4_netmask = ipv4_netmask
         else:
             self.ipv4_netmask = 0
+        return
 
     def pack(self):
         packed = []
         packed.append(struct.pack("!6B", *self.hw_addr))
-        packed.append(struct.pack("!H", self.pad))
+        packed.append('\x00' * 2)
         packed.append(struct.pack("!16s", self.name))
         packed.append(struct.pack("!L", self.ipv4_addr))
         packed.append(struct.pack("!L", self.ipv4_netmask))
@@ -97,19 +88,21 @@
 
     @staticmethod
     def unpack(buf):
-        assert(len(buf) >= 32) # Should be verified by caller
         obj = bsn_interface()
-        obj.hw_addr = list(struct.unpack_from('!6B', buf, 0))
-        obj.pad = struct.unpack_from('!H', buf, 6)[0]
-        obj.name = str(buffer(buf, 8, 16)).rstrip("\x00")
-        obj.ipv4_addr = struct.unpack_from('!L', buf, 24)[0]
-        obj.ipv4_netmask = struct.unpack_from('!L', buf, 28)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.hw_addr = list(reader.read('!6B'))
+        reader.skip(2)
+        obj.name = reader.read("!16s")[0].rstrip("\x00")
+        obj.ipv4_addr = reader.read('!L')[0]
+        obj.ipv4_netmask = reader.read('!L')[0]
         return obj
 
     def __eq__(self, other):
         if type(self) != type(other): return False
         if self.hw_addr != other.hw_addr: return False
-        if self.pad != other.pad: return False
         if self.name != other.name: return False
         if self.ipv4_addr != other.ipv4_addr: return False
         if self.ipv4_netmask != other.ipv4_netmask: return False
@@ -130,9 +123,6 @@
                 q.text("hw_addr = ");
                 q.text(util.pretty_mac(self.hw_addr))
                 q.text(","); q.breakable()
-                q.text("pad = ");
-                q.text("%#x" % self.pad)
-                q.text(","); q.breakable()
                 q.text("name = ");
                 q.pp(self.name)
                 q.text(","); q.breakable()
@@ -146,15 +136,11 @@
 
 class flow_stats_entry(object):
 
-    def __init__(self, table_id=None, pad=None, match=None, duration_sec=None, duration_nsec=None, priority=None, idle_timeout=None, hard_timeout=None, pad2=None, cookie=None, packet_count=None, byte_count=None, actions=None):
+    def __init__(self, table_id=None, match=None, duration_sec=None, duration_nsec=None, priority=None, idle_timeout=None, hard_timeout=None, cookie=None, packet_count=None, byte_count=None, actions=None):
         if table_id != None:
             self.table_id = table_id
         else:
             self.table_id = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = 0
         if match != None:
             self.match = match
         else:
@@ -179,10 +165,6 @@
             self.hard_timeout = hard_timeout
         else:
             self.hard_timeout = 0
-        if pad2 != None:
-            self.pad2 = pad2
-        else:
-            self.pad2 = [0,0,0,0,0,0]
         if cookie != None:
             self.cookie = cookie
         else:
@@ -199,19 +181,20 @@
             self.actions = actions
         else:
             self.actions = []
+        return
 
     def pack(self):
         packed = []
         packed.append(struct.pack("!H", 0)) # placeholder for length at index 0
         packed.append(struct.pack("!B", self.table_id))
-        packed.append(struct.pack("!B", self.pad))
+        packed.append('\x00' * 1)
         packed.append(self.match.pack())
         packed.append(struct.pack("!L", self.duration_sec))
         packed.append(struct.pack("!L", self.duration_nsec))
         packed.append(struct.pack("!H", self.priority))
         packed.append(struct.pack("!H", self.idle_timeout))
         packed.append(struct.pack("!H", self.hard_timeout))
-        packed.append(struct.pack("!6B", *self.pad2))
+        packed.append('\x00' * 6)
         packed.append(struct.pack("!Q", self.cookie))
         packed.append(struct.pack("!Q", self.packet_count))
         packed.append(struct.pack("!Q", self.byte_count))
@@ -222,37 +205,36 @@
 
     @staticmethod
     def unpack(buf):
-        assert(len(buf) >= 88) # Should be verified by caller
         obj = flow_stats_entry()
-        _length = struct.unpack_from('!H', buf, 0)[0]
-        assert(_length == len(buf))
-        if _length < 88: raise loxi.ProtocolError("flow_stats_entry length is %d, should be at least 88" % _length)
-        obj.table_id = struct.unpack_from('!B', buf, 2)[0]
-        obj.pad = struct.unpack_from('!B', buf, 3)[0]
-        obj.match = common.match.unpack(buffer(buf, 4))
-        obj.duration_sec = struct.unpack_from('!L', buf, 44)[0]
-        obj.duration_nsec = struct.unpack_from('!L', buf, 48)[0]
-        obj.priority = struct.unpack_from('!H', buf, 52)[0]
-        obj.idle_timeout = struct.unpack_from('!H', buf, 54)[0]
-        obj.hard_timeout = struct.unpack_from('!H', buf, 56)[0]
-        obj.pad2 = list(struct.unpack_from('!6B', buf, 58))
-        obj.cookie = struct.unpack_from('!Q', buf, 64)[0]
-        obj.packet_count = struct.unpack_from('!Q', buf, 72)[0]
-        obj.byte_count = struct.unpack_from('!Q', buf, 80)[0]
-        obj.actions = action.unpack_list(buffer(buf, 88))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _length = reader.read('!H')[0]
+        obj.table_id = reader.read('!B')[0]
+        reader.skip(1)
+        obj.match = common.match.unpack(reader)
+        obj.duration_sec = reader.read('!L')[0]
+        obj.duration_nsec = reader.read('!L')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        reader.skip(6)
+        obj.cookie = reader.read('!Q')[0]
+        obj.packet_count = reader.read('!Q')[0]
+        obj.byte_count = reader.read('!Q')[0]
+        obj.actions = action.unpack_list(reader)
         return obj
 
     def __eq__(self, other):
         if type(self) != type(other): return False
         if self.table_id != other.table_id: return False
-        if self.pad != other.pad: return False
         if self.match != other.match: return False
         if self.duration_sec != other.duration_sec: return False
         if self.duration_nsec != other.duration_nsec: return False
         if self.priority != other.priority: return False
         if self.idle_timeout != other.idle_timeout: return False
         if self.hard_timeout != other.hard_timeout: return False
-        if self.pad2 != other.pad2: return False
         if self.cookie != other.cookie: return False
         if self.packet_count != other.packet_count: return False
         if self.byte_count != other.byte_count: return False
@@ -274,9 +256,6 @@
                 q.text("table_id = ");
                 q.text("%#x" % self.table_id)
                 q.text(","); q.breakable()
-                q.text("pad = ");
-                q.text("%#x" % self.pad)
-                q.text(","); q.breakable()
                 q.text("match = ");
                 q.pp(self.match)
                 q.text(","); q.breakable()
@@ -295,9 +274,6 @@
                 q.text("hard_timeout = ");
                 q.text("%#x" % self.hard_timeout)
                 q.text(","); q.breakable()
-                q.text("pad2 = ");
-                q.pp(self.pad2)
-                q.text(","); q.breakable()
                 q.text("cookie = ");
                 q.text("%#x" % self.cookie)
                 q.text(","); q.breakable()
@@ -314,7 +290,7 @@
 
 class match_v1(object):
 
-    def __init__(self, wildcards=None, in_port=None, eth_src=None, eth_dst=None, vlan_vid=None, vlan_pcp=None, pad1=None, eth_type=None, ip_dscp=None, ip_proto=None, pad2=None, ipv4_src=None, ipv4_dst=None, tcp_src=None, tcp_dst=None):
+    def __init__(self, wildcards=None, in_port=None, eth_src=None, eth_dst=None, vlan_vid=None, vlan_pcp=None, eth_type=None, ip_dscp=None, ip_proto=None, ipv4_src=None, ipv4_dst=None, tcp_src=None, tcp_dst=None):
         if wildcards != None:
             self.wildcards = wildcards
         else:
@@ -339,10 +315,6 @@
             self.vlan_pcp = vlan_pcp
         else:
             self.vlan_pcp = 0
-        if pad1 != None:
-            self.pad1 = pad1
-        else:
-            self.pad1 = 0
         if eth_type != None:
             self.eth_type = eth_type
         else:
@@ -355,10 +327,6 @@
             self.ip_proto = ip_proto
         else:
             self.ip_proto = 0
-        if pad2 != None:
-            self.pad2 = pad2
-        else:
-            self.pad2 = [0,0]
         if ipv4_src != None:
             self.ipv4_src = ipv4_src
         else:
@@ -375,6 +343,7 @@
             self.tcp_dst = tcp_dst
         else:
             self.tcp_dst = 0
+        return
 
     def pack(self):
         packed = []
@@ -384,11 +353,11 @@
         packed.append(struct.pack("!6B", *self.eth_dst))
         packed.append(struct.pack("!H", self.vlan_vid))
         packed.append(struct.pack("!B", self.vlan_pcp))
-        packed.append(struct.pack("!B", self.pad1))
+        packed.append('\x00' * 1)
         packed.append(struct.pack("!H", self.eth_type))
         packed.append(struct.pack("!B", self.ip_dscp))
         packed.append(struct.pack("!B", self.ip_proto))
-        packed.append(struct.pack("!2B", *self.pad2))
+        packed.append('\x00' * 2)
         packed.append(struct.pack("!L", self.ipv4_src))
         packed.append(struct.pack("!L", self.ipv4_dst))
         packed.append(struct.pack("!H", self.tcp_src))
@@ -397,23 +366,26 @@
 
     @staticmethod
     def unpack(buf):
-        assert(len(buf) >= 40) # Should be verified by caller
         obj = match_v1()
-        obj.wildcards = struct.unpack_from('!L', buf, 0)[0]
-        obj.in_port = struct.unpack_from('!H', buf, 4)[0]
-        obj.eth_src = list(struct.unpack_from('!6B', buf, 6))
-        obj.eth_dst = list(struct.unpack_from('!6B', buf, 12))
-        obj.vlan_vid = struct.unpack_from('!H', buf, 18)[0]
-        obj.vlan_pcp = struct.unpack_from('!B', buf, 20)[0]
-        obj.pad1 = struct.unpack_from('!B', buf, 21)[0]
-        obj.eth_type = struct.unpack_from('!H', buf, 22)[0]
-        obj.ip_dscp = struct.unpack_from('!B', buf, 24)[0]
-        obj.ip_proto = struct.unpack_from('!B', buf, 25)[0]
-        obj.pad2 = list(struct.unpack_from('!2B', buf, 26))
-        obj.ipv4_src = struct.unpack_from('!L', buf, 28)[0]
-        obj.ipv4_dst = struct.unpack_from('!L', buf, 32)[0]
-        obj.tcp_src = struct.unpack_from('!H', buf, 36)[0]
-        obj.tcp_dst = struct.unpack_from('!H', buf, 38)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.wildcards = reader.read('!L')[0]
+        obj.in_port = reader.read('!H')[0]
+        obj.eth_src = list(reader.read('!6B'))
+        obj.eth_dst = list(reader.read('!6B'))
+        obj.vlan_vid = reader.read('!H')[0]
+        obj.vlan_pcp = reader.read('!B')[0]
+        reader.skip(1)
+        obj.eth_type = reader.read('!H')[0]
+        obj.ip_dscp = reader.read('!B')[0]
+        obj.ip_proto = reader.read('!B')[0]
+        reader.skip(2)
+        obj.ipv4_src = reader.read('!L')[0]
+        obj.ipv4_dst = reader.read('!L')[0]
+        obj.tcp_src = reader.read('!H')[0]
+        obj.tcp_dst = reader.read('!H')[0]
         return obj
 
     def __eq__(self, other):
@@ -424,11 +396,9 @@
         if self.eth_dst != other.eth_dst: return False
         if self.vlan_vid != other.vlan_vid: return False
         if self.vlan_pcp != other.vlan_pcp: return False
-        if self.pad1 != other.pad1: return False
         if self.eth_type != other.eth_type: return False
         if self.ip_dscp != other.ip_dscp: return False
         if self.ip_proto != other.ip_proto: return False
-        if self.pad2 != other.pad2: return False
         if self.ipv4_src != other.ipv4_src: return False
         if self.ipv4_dst != other.ipv4_dst: return False
         if self.tcp_src != other.tcp_src: return False
@@ -465,9 +435,6 @@
                 q.text("vlan_pcp = ");
                 q.text("%#x" % self.vlan_pcp)
                 q.text(","); q.breakable()
-                q.text("pad1 = ");
-                q.text("%#x" % self.pad1)
-                q.text(","); q.breakable()
                 q.text("eth_type = ");
                 q.text("%#x" % self.eth_type)
                 q.text(","); q.breakable()
@@ -477,9 +444,6 @@
                 q.text("ip_proto = ");
                 q.text("%#x" % self.ip_proto)
                 q.text(","); q.breakable()
-                q.text("pad2 = ");
-                q.pp(self.pad2)
-                q.text(","); q.breakable()
                 q.text("ipv4_src = ");
                 q.text(util.pretty_ipv4(self.ipv4_src))
                 q.text(","); q.breakable()
@@ -494,29 +458,24 @@
             q.breakable()
         q.text('}')
 
-match = match_v1
-
 class packet_queue(object):
 
-    def __init__(self, queue_id=None, pad=None, properties=None):
+    def __init__(self, queue_id=None, properties=None):
         if queue_id != None:
             self.queue_id = queue_id
         else:
             self.queue_id = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0]
         if properties != None:
             self.properties = properties
         else:
             self.properties = []
+        return
 
     def pack(self):
         packed = []
         packed.append(struct.pack("!L", self.queue_id))
         packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
-        packed.append(struct.pack("!2B", *self.pad))
+        packed.append('\x00' * 2)
         packed.append("".join([x.pack() for x in self.properties]))
         length = sum([len(x) for x in packed])
         packed[1] = struct.pack("!H", length)
@@ -524,20 +483,20 @@
 
     @staticmethod
     def unpack(buf):
-        assert(len(buf) >= 8) # Should be verified by caller
         obj = packet_queue()
-        obj.queue_id = struct.unpack_from('!L', buf, 0)[0]
-        _length = struct.unpack_from('!H', buf, 4)[0]
-        assert(_length == len(buf))
-        if _length < 8: raise loxi.ProtocolError("packet_queue length is %d, should be at least 8" % _length)
-        obj.pad = list(struct.unpack_from('!2B', buf, 6))
-        obj.properties = common.unpack_list_queue_prop(buffer(buf, 8))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.queue_id = reader.read('!L')[0]
+        _len = reader.read('!H')[0]
+        reader.skip(2)
+        obj.properties = common.unpack_list_queue_prop(reader)
         return obj
 
     def __eq__(self, other):
         if type(self) != type(other): return False
         if self.queue_id != other.queue_id: return False
-        if self.pad != other.pad: return False
         if self.properties != other.properties: return False
         return True
 
@@ -556,9 +515,6 @@
                 q.text("queue_id = ");
                 q.text("%#x" % self.queue_id)
                 q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
-                q.text(","); q.breakable()
                 q.text("properties = ");
                 q.pp(self.properties)
             q.breakable()
@@ -603,6 +559,7 @@
             self.peer = peer
         else:
             self.peer = 0
+        return
 
     def pack(self):
         packed = []
@@ -619,17 +576,20 @@
 
     @staticmethod
     def unpack(buf):
-        assert(len(buf) >= 48) # Should be verified by caller
         obj = port_desc()
-        obj.port_no = struct.unpack_from('!H', buf, 0)[0]
-        obj.hw_addr = list(struct.unpack_from('!6B', buf, 2))
-        obj.name = str(buffer(buf, 8, 16)).rstrip("\x00")
-        obj.config = struct.unpack_from('!L', buf, 24)[0]
-        obj.state = struct.unpack_from('!L', buf, 28)[0]
-        obj.curr = struct.unpack_from('!L', buf, 32)[0]
-        obj.advertised = struct.unpack_from('!L', buf, 36)[0]
-        obj.supported = struct.unpack_from('!L', buf, 40)[0]
-        obj.peer = struct.unpack_from('!L', buf, 44)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.port_no = reader.read('!H')[0]
+        obj.hw_addr = list(reader.read('!6B'))
+        obj.name = reader.read("!16s")[0].rstrip("\x00")
+        obj.config = reader.read('!L')[0]
+        obj.state = reader.read('!L')[0]
+        obj.curr = reader.read('!L')[0]
+        obj.advertised = reader.read('!L')[0]
+        obj.supported = reader.read('!L')[0]
+        obj.peer = reader.read('!L')[0]
         return obj
 
     def __eq__(self, other):
@@ -688,15 +648,11 @@
 
 class port_stats_entry(object):
 
-    def __init__(self, port_no=None, pad=None, rx_packets=None, tx_packets=None, rx_bytes=None, tx_bytes=None, rx_dropped=None, tx_dropped=None, rx_errors=None, tx_errors=None, rx_frame_err=None, rx_over_err=None, rx_crc_err=None, collisions=None):
+    def __init__(self, port_no=None, rx_packets=None, tx_packets=None, rx_bytes=None, tx_bytes=None, rx_dropped=None, tx_dropped=None, rx_errors=None, tx_errors=None, rx_frame_err=None, rx_over_err=None, rx_crc_err=None, collisions=None):
         if port_no != None:
             self.port_no = port_no
         else:
             self.port_no = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0,0,0,0,0]
         if rx_packets != None:
             self.rx_packets = rx_packets
         else:
@@ -745,11 +701,12 @@
             self.collisions = collisions
         else:
             self.collisions = 0
+        return
 
     def pack(self):
         packed = []
         packed.append(struct.pack("!H", self.port_no))
-        packed.append(struct.pack("!6B", *self.pad))
+        packed.append('\x00' * 6)
         packed.append(struct.pack("!Q", self.rx_packets))
         packed.append(struct.pack("!Q", self.tx_packets))
         packed.append(struct.pack("!Q", self.rx_bytes))
@@ -766,28 +723,30 @@
 
     @staticmethod
     def unpack(buf):
-        assert(len(buf) >= 104) # Should be verified by caller
         obj = port_stats_entry()
-        obj.port_no = struct.unpack_from('!H', buf, 0)[0]
-        obj.pad = list(struct.unpack_from('!6B', buf, 2))
-        obj.rx_packets = struct.unpack_from('!Q', buf, 8)[0]
-        obj.tx_packets = struct.unpack_from('!Q', buf, 16)[0]
-        obj.rx_bytes = struct.unpack_from('!Q', buf, 24)[0]
-        obj.tx_bytes = struct.unpack_from('!Q', buf, 32)[0]
-        obj.rx_dropped = struct.unpack_from('!Q', buf, 40)[0]
-        obj.tx_dropped = struct.unpack_from('!Q', buf, 48)[0]
-        obj.rx_errors = struct.unpack_from('!Q', buf, 56)[0]
-        obj.tx_errors = struct.unpack_from('!Q', buf, 64)[0]
-        obj.rx_frame_err = struct.unpack_from('!Q', buf, 72)[0]
-        obj.rx_over_err = struct.unpack_from('!Q', buf, 80)[0]
-        obj.rx_crc_err = struct.unpack_from('!Q', buf, 88)[0]
-        obj.collisions = struct.unpack_from('!Q', buf, 96)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.port_no = reader.read('!H')[0]
+        reader.skip(6)
+        obj.rx_packets = reader.read('!Q')[0]
+        obj.tx_packets = reader.read('!Q')[0]
+        obj.rx_bytes = reader.read('!Q')[0]
+        obj.tx_bytes = reader.read('!Q')[0]
+        obj.rx_dropped = reader.read('!Q')[0]
+        obj.tx_dropped = reader.read('!Q')[0]
+        obj.rx_errors = reader.read('!Q')[0]
+        obj.tx_errors = reader.read('!Q')[0]
+        obj.rx_frame_err = reader.read('!Q')[0]
+        obj.rx_over_err = reader.read('!Q')[0]
+        obj.rx_crc_err = reader.read('!Q')[0]
+        obj.collisions = reader.read('!Q')[0]
         return obj
 
     def __eq__(self, other):
         if type(self) != type(other): return False
         if self.port_no != other.port_no: return False
-        if self.pad != other.pad: return False
         if self.rx_packets != other.rx_packets: return False
         if self.tx_packets != other.tx_packets: return False
         if self.rx_bytes != other.rx_bytes: return False
@@ -817,9 +776,6 @@
                 q.text("port_no = ");
                 q.text(util.pretty_port(self.port_no))
                 q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
-                q.text(","); q.breakable()
                 q.text("rx_packets = ");
                 q.text("%#x" % self.rx_packets)
                 q.text(","); q.breakable()
@@ -861,50 +817,42 @@
 class queue_prop_min_rate(object):
     type = const.OFPQT_MIN_RATE
 
-    def __init__(self, pad=None, rate=None, pad2=None):
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0,0,0]
+    def __init__(self, rate=None):
         if rate != None:
             self.rate = rate
         else:
             self.rate = 0
-        if pad2 != None:
-            self.pad2 = pad2
-        else:
-            self.pad2 = [0,0,0,0,0,0]
+        return
 
     def pack(self):
         packed = []
         packed.append(struct.pack("!H", self.type))
         packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
-        packed.append(struct.pack("!4B", *self.pad))
+        packed.append('\x00' * 4)
         packed.append(struct.pack("!H", self.rate))
-        packed.append(struct.pack("!6B", *self.pad2))
+        packed.append('\x00' * 6)
         length = sum([len(x) for x in packed])
         packed[1] = struct.pack("!H", length)
         return ''.join(packed)
 
     @staticmethod
     def unpack(buf):
-        assert(len(buf) >= 16) # Should be verified by caller
         obj = queue_prop_min_rate()
-        type = struct.unpack_from('!H', buf, 0)[0]
-        assert(type == const.OFPQT_MIN_RATE)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 16: raise loxi.ProtocolError("queue_prop_min_rate length is %d, should be 16" % _length)
-        obj.pad = list(struct.unpack_from('!4B', buf, 4))
-        obj.rate = struct.unpack_from('!H', buf, 8)[0]
-        obj.pad2 = list(struct.unpack_from('!6B', buf, 10))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPQT_MIN_RATE)
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        obj.rate = reader.read('!H')[0]
+        reader.skip(6)
         return obj
 
     def __eq__(self, other):
         if type(self) != type(other): return False
-        if self.pad != other.pad: return False
         if self.rate != other.rate: return False
-        if self.pad2 != other.pad2: return False
         return True
 
     def __ne__(self, other):
@@ -919,28 +867,18 @@
         with q.group():
             with q.indent(2):
                 q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
-                q.text(","); q.breakable()
                 q.text("rate = ");
                 q.text("%#x" % self.rate)
-                q.text(","); q.breakable()
-                q.text("pad2 = ");
-                q.pp(self.pad2)
             q.breakable()
         q.text('}')
 
 class queue_stats_entry(object):
 
-    def __init__(self, port_no=None, pad=None, queue_id=None, tx_bytes=None, tx_packets=None, tx_errors=None):
+    def __init__(self, port_no=None, queue_id=None, tx_bytes=None, tx_packets=None, tx_errors=None):
         if port_no != None:
             self.port_no = port_no
         else:
             self.port_no = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0]
         if queue_id != None:
             self.queue_id = queue_id
         else:
@@ -957,11 +895,12 @@
             self.tx_errors = tx_errors
         else:
             self.tx_errors = 0
+        return
 
     def pack(self):
         packed = []
         packed.append(struct.pack("!H", self.port_no))
-        packed.append(struct.pack("!2B", *self.pad))
+        packed.append('\x00' * 2)
         packed.append(struct.pack("!L", self.queue_id))
         packed.append(struct.pack("!Q", self.tx_bytes))
         packed.append(struct.pack("!Q", self.tx_packets))
@@ -970,20 +909,22 @@
 
     @staticmethod
     def unpack(buf):
-        assert(len(buf) >= 32) # Should be verified by caller
         obj = queue_stats_entry()
-        obj.port_no = struct.unpack_from('!H', buf, 0)[0]
-        obj.pad = list(struct.unpack_from('!2B', buf, 2))
-        obj.queue_id = struct.unpack_from('!L', buf, 4)[0]
-        obj.tx_bytes = struct.unpack_from('!Q', buf, 8)[0]
-        obj.tx_packets = struct.unpack_from('!Q', buf, 16)[0]
-        obj.tx_errors = struct.unpack_from('!Q', buf, 24)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.port_no = reader.read('!H')[0]
+        reader.skip(2)
+        obj.queue_id = reader.read('!L')[0]
+        obj.tx_bytes = reader.read('!Q')[0]
+        obj.tx_packets = reader.read('!Q')[0]
+        obj.tx_errors = reader.read('!Q')[0]
         return obj
 
     def __eq__(self, other):
         if type(self) != type(other): return False
         if self.port_no != other.port_no: return False
-        if self.pad != other.pad: return False
         if self.queue_id != other.queue_id: return False
         if self.tx_bytes != other.tx_bytes: return False
         if self.tx_packets != other.tx_packets: return False
@@ -1005,9 +946,6 @@
                 q.text("port_no = ");
                 q.text(util.pretty_port(self.port_no))
                 q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
-                q.text(","); q.breakable()
                 q.text("queue_id = ");
                 q.text("%#x" % self.queue_id)
                 q.text(","); q.breakable()
@@ -1024,15 +962,11 @@
 
 class table_stats_entry(object):
 
-    def __init__(self, table_id=None, pad=None, name=None, wildcards=None, max_entries=None, active_count=None, lookup_count=None, matched_count=None):
+    def __init__(self, table_id=None, name=None, wildcards=None, max_entries=None, active_count=None, lookup_count=None, matched_count=None):
         if table_id != None:
             self.table_id = table_id
         else:
             self.table_id = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0,0]
         if name != None:
             self.name = name
         else:
@@ -1057,11 +991,12 @@
             self.matched_count = matched_count
         else:
             self.matched_count = 0
+        return
 
     def pack(self):
         packed = []
         packed.append(struct.pack("!B", self.table_id))
-        packed.append(struct.pack("!3B", *self.pad))
+        packed.append('\x00' * 3)
         packed.append(struct.pack("!32s", self.name))
         packed.append(struct.pack("!L", self.wildcards))
         packed.append(struct.pack("!L", self.max_entries))
@@ -1072,22 +1007,24 @@
 
     @staticmethod
     def unpack(buf):
-        assert(len(buf) >= 64) # Should be verified by caller
         obj = table_stats_entry()
-        obj.table_id = struct.unpack_from('!B', buf, 0)[0]
-        obj.pad = list(struct.unpack_from('!3B', buf, 1))
-        obj.name = str(buffer(buf, 4, 32)).rstrip("\x00")
-        obj.wildcards = struct.unpack_from('!L', buf, 36)[0]
-        obj.max_entries = struct.unpack_from('!L', buf, 40)[0]
-        obj.active_count = struct.unpack_from('!L', buf, 44)[0]
-        obj.lookup_count = struct.unpack_from('!Q', buf, 48)[0]
-        obj.matched_count = struct.unpack_from('!Q', buf, 56)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.table_id = reader.read('!B')[0]
+        reader.skip(3)
+        obj.name = reader.read("!32s")[0].rstrip("\x00")
+        obj.wildcards = reader.read('!L')[0]
+        obj.max_entries = reader.read('!L')[0]
+        obj.active_count = reader.read('!L')[0]
+        obj.lookup_count = reader.read('!Q')[0]
+        obj.matched_count = reader.read('!Q')[0]
         return obj
 
     def __eq__(self, other):
         if type(self) != type(other): return False
         if self.table_id != other.table_id: return False
-        if self.pad != other.pad: return False
         if self.name != other.name: return False
         if self.wildcards != other.wildcards: return False
         if self.max_entries != other.max_entries: return False
@@ -1111,9 +1048,6 @@
                 q.text("table_id = ");
                 q.text("%#x" % self.table_id)
                 q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
-                q.text(","); q.breakable()
                 q.text("name = ");
                 q.pp(self.name)
                 q.text(","); q.breakable()
@@ -1134,3 +1068,5 @@
             q.breakable()
         q.text('}')
 
+
+match = match_v1
diff --git a/src/python/loxi/of10/const.py b/src/python/loxi/of10/const.py
index e269071..3b9a177 100644
--- a/src/python/loxi/of10/const.py
+++ b/src/python/loxi/of10/const.py
@@ -1,17 +1,6 @@
-#
-# Copyright 2012, 2013, Big Switch Networks, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
 
 # Automatically generated by LOXI from template const.py
 # Do not modify
@@ -24,18 +13,18 @@
 OFP_MAX_PORT_NAME_LEN = 16
 OFP_MAX_TABLE_NAME_LEN = 32
 SERIAL_NUM_LEN = 32
-OFPFW_ICMP_TYPE = (1 << 6)
-OFPFW_ICMP_CODE = (1 << 7)
+OFPFW_ICMP_TYPE = 64
 OFP_DEFAULT_MISS_SEND_LEN = 128
+OFPFW_ICMP_CODE = 128
 DESC_STR_LEN = 256
-OFP_DL_TYPE_NOT_ETH_TYPE = 0x05ff
-OFP_DL_TYPE_ETH2_CUTOFF = 0x0600
+OFP_DL_TYPE_NOT_ETH_TYPE = 1535
+OFP_DL_TYPE_ETH2_CUTOFF = 1536
 OFP_TCP_PORT = 6633
 OFP_SSL_PORT = 6633
-OFP_DEFAULT_PRIORITY = 0x8000
-OFPQ_MIN_RATE_UNCFG = 0xffff
-OFP_VLAN_NONE = 0xffff
-OFPQ_ALL = 0xffffffff
+OFP_DEFAULT_PRIORITY = 32768
+OFP_VLAN_NONE = 65535
+OFPQ_MIN_RATE_UNCFG = 65535
+OFPQ_ALL = 4294967295
 
 # Identifiers from group ofp_action_type
 OFPAT_OUTPUT = 0
@@ -50,7 +39,7 @@
 OFPAT_SET_TP_SRC = 9
 OFPAT_SET_TP_DST = 10
 OFPAT_ENQUEUE = 11
-OFPAT_VENDOR = 0xffff
+OFPAT_VENDOR = 65535
 
 ofp_action_type_map = {
     0: 'OFPAT_OUTPUT',
@@ -65,7 +54,7 @@
     9: 'OFPAT_SET_TP_SRC',
     10: 'OFPAT_SET_TP_DST',
     11: 'OFPAT_ENQUEUE',
-    0xffff: 'OFPAT_VENDOR',
+    65535: 'OFPAT_VENDOR',
 }
 
 # Identifiers from group ofp_bad_action_code
@@ -115,24 +104,24 @@
 }
 
 # Identifiers from group ofp_capabilities
-OFPC_FLOW_STATS = 1 << 0
-OFPC_TABLE_STATS = 1 << 1
-OFPC_PORT_STATS = 1 << 2
-OFPC_STP = 1 << 3
-OFPC_RESERVED = 1 << 4
-OFPC_IP_REASM = 1 << 5
-OFPC_QUEUE_STATS = 1 << 6
-OFPC_ARP_MATCH_IP = 1 << 7
+OFPC_FLOW_STATS = 1
+OFPC_TABLE_STATS = 2
+OFPC_PORT_STATS = 4
+OFPC_STP = 8
+OFPC_RESERVED = 16
+OFPC_IP_REASM = 32
+OFPC_QUEUE_STATS = 64
+OFPC_ARP_MATCH_IP = 128
 
 ofp_capabilities_map = {
-    1 << 0: 'OFPC_FLOW_STATS',
-    1 << 1: 'OFPC_TABLE_STATS',
-    1 << 2: 'OFPC_PORT_STATS',
-    1 << 3: 'OFPC_STP',
-    1 << 4: 'OFPC_RESERVED',
-    1 << 5: 'OFPC_IP_REASM',
-    1 << 6: 'OFPC_QUEUE_STATS',
-    1 << 7: 'OFPC_ARP_MATCH_IP',
+    1: 'OFPC_FLOW_STATS',
+    2: 'OFPC_TABLE_STATS',
+    4: 'OFPC_PORT_STATS',
+    8: 'OFPC_STP',
+    16: 'OFPC_RESERVED',
+    32: 'OFPC_IP_REASM',
+    64: 'OFPC_QUEUE_STATS',
+    128: 'OFPC_ARP_MATCH_IP',
 }
 
 # Identifiers from group ofp_config_flags
@@ -198,14 +187,14 @@
 }
 
 # Identifiers from group ofp_flow_mod_flags
-OFPFF_SEND_FLOW_REM = 1 << 0
-OFPFF_CHECK_OVERLAP = 1 << 1
-OFPFF_EMERG = 1 << 2
+OFPFF_SEND_FLOW_REM = 1
+OFPFF_CHECK_OVERLAP = 2
+OFPFF_EMERG = 4
 
 ofp_flow_mod_flags_map = {
-    1 << 0: 'OFPFF_SEND_FLOW_REM',
-    1 << 1: 'OFPFF_CHECK_OVERLAP',
-    1 << 2: 'OFPFF_EMERG',
+    1: 'OFPFF_SEND_FLOW_REM',
+    2: 'OFPFF_CHECK_OVERLAP',
+    4: 'OFPFF_EMERG',
 }
 
 # Identifiers from group ofp_flow_removed_reason
@@ -220,37 +209,37 @@
 }
 
 # Identifiers from group ofp_flow_wildcards
-OFPFW_IN_PORT = 1 << 0
-OFPFW_DL_VLAN = 1 << 1
-OFPFW_DL_SRC = 1 << 2
+OFPFW_IN_PORT = 1
+OFPFW_DL_VLAN = 2
+OFPFW_DL_SRC = 4
 OFPFW_NW_DST_BITS = 6
 OFPFW_NW_SRC_BITS = 6
 OFPFW_NW_SRC_SHIFT = 8
-OFPFW_DL_DST = 1 << 3
+OFPFW_DL_DST = 8
 OFPFW_NW_DST_SHIFT = 14
-OFPFW_DL_TYPE = 1 << 4
-OFPFW_NW_PROTO = 1 << 5
-OFPFW_TP_SRC = 1 << 6
-OFPFW_TP_DST = 1 << 7
-OFPFW_NW_SRC_ALL = 32 << (8)
-OFPFW_NW_SRC_MASK = ((1 << (6)) - 1) << (8)
-OFPFW_NW_DST_ALL = 32 << (14)
-OFPFW_NW_DST_MASK = ((1 << (6)) - 1) << (14)
-OFPFW_DL_VLAN_PCP = 1 << 20
-OFPFW_NW_TOS = 1 << 21
-OFPFW_ALL = ((1 << 22) - 1)
+OFPFW_DL_TYPE = 16
+OFPFW_NW_PROTO = 32
+OFPFW_TP_SRC = 64
+OFPFW_TP_DST = 128
+OFPFW_NW_SRC_ALL = 8192
+OFPFW_NW_SRC_MASK = 16128
+OFPFW_NW_DST_ALL = 524288
+OFPFW_NW_DST_MASK = 1032192
+OFPFW_DL_VLAN_PCP = 1048576
+OFPFW_NW_TOS = 2097152
+OFPFW_ALL = 4194303
 
 ofp_flow_wildcards_map = {
-    1 << 0: 'OFPFW_IN_PORT',
-    1 << 1: 'OFPFW_DL_VLAN',
-    1 << 2: 'OFPFW_DL_SRC',
-    1 << 3: 'OFPFW_DL_DST',
-    1 << 4: 'OFPFW_DL_TYPE',
-    1 << 5: 'OFPFW_NW_PROTO',
-    1 << 6: 'OFPFW_TP_SRC',
-    1 << 7: 'OFPFW_TP_DST',
-    1 << 20: 'OFPFW_DL_VLAN_PCP',
-    1 << 21: 'OFPFW_NW_TOS',
+    1: 'OFPFW_IN_PORT',
+    2: 'OFPFW_DL_VLAN',
+    4: 'OFPFW_DL_SRC',
+    8: 'OFPFW_DL_DST',
+    16: 'OFPFW_DL_TYPE',
+    32: 'OFPFW_NW_PROTO',
+    64: 'OFPFW_TP_SRC',
+    128: 'OFPFW_TP_DST',
+    1048576: 'OFPFW_DL_VLAN_PCP',
+    2097152: 'OFPFW_NW_TOS',
 }
 
 # Identifiers from group ofp_hello_failed_code
@@ -262,6 +251,17 @@
     1: 'OFPHFC_EPERM',
 }
 
+# Identifiers from group ofp_nicira_controller_role
+NX_ROLE_OTHER = 0
+NX_ROLE_MASTER = 1
+NX_ROLE_SLAVE = 2
+
+ofp_nicira_controller_role_map = {
+    0: 'NX_ROLE_OTHER',
+    1: 'NX_ROLE_MASTER',
+    2: 'NX_ROLE_SLAVE',
+}
+
 # Identifiers from group ofp_packet_in_reason
 OFPR_NO_MATCH = 0
 OFPR_ACTION = 1
@@ -295,51 +295,51 @@
 }
 
 # Identifiers from group ofp_port_config
-OFPPC_PORT_DOWN = 1 << 0
-OFPPC_NO_STP = 1 << 1
-OFPPC_NO_RECV = 1 << 2
-OFPPC_NO_RECV_STP = 1 << 3
-OFPPC_NO_FLOOD = 1 << 4
-OFPPC_NO_FWD = 1 << 5
-OFPPC_NO_PACKET_IN = 1 << 6
+OFPPC_PORT_DOWN = 1
+OFPPC_NO_STP = 2
+OFPPC_NO_RECV = 4
+OFPPC_NO_RECV_STP = 8
+OFPPC_NO_FLOOD = 16
+OFPPC_NO_FWD = 32
+OFPPC_NO_PACKET_IN = 64
 
 ofp_port_config_map = {
-    1 << 0: 'OFPPC_PORT_DOWN',
-    1 << 1: 'OFPPC_NO_STP',
-    1 << 2: 'OFPPC_NO_RECV',
-    1 << 3: 'OFPPC_NO_RECV_STP',
-    1 << 4: 'OFPPC_NO_FLOOD',
-    1 << 5: 'OFPPC_NO_FWD',
-    1 << 6: 'OFPPC_NO_PACKET_IN',
+    1: 'OFPPC_PORT_DOWN',
+    2: 'OFPPC_NO_STP',
+    4: 'OFPPC_NO_RECV',
+    8: 'OFPPC_NO_RECV_STP',
+    16: 'OFPPC_NO_FLOOD',
+    32: 'OFPPC_NO_FWD',
+    64: 'OFPPC_NO_PACKET_IN',
 }
 
 # Identifiers from group ofp_port_features
-OFPPF_10MB_HD = 1 << 0
-OFPPF_10MB_FD = 1 << 1
-OFPPF_100MB_HD = 1 << 2
-OFPPF_100MB_FD = 1 << 3
-OFPPF_1GB_HD = 1 << 4
-OFPPF_1GB_FD = 1 << 5
-OFPPF_10GB_FD = 1 << 6
-OFPPF_COPPER = 1 << 7
-OFPPF_FIBER = 1 << 8
-OFPPF_AUTONEG = 1 << 9
-OFPPF_PAUSE = 1 << 10
-OFPPF_PAUSE_ASYM = 1 << 11
+OFPPF_10MB_HD = 1
+OFPPF_10MB_FD = 2
+OFPPF_100MB_HD = 4
+OFPPF_100MB_FD = 8
+OFPPF_1GB_HD = 16
+OFPPF_1GB_FD = 32
+OFPPF_10GB_FD = 64
+OFPPF_COPPER = 128
+OFPPF_FIBER = 256
+OFPPF_AUTONEG = 512
+OFPPF_PAUSE = 1024
+OFPPF_PAUSE_ASYM = 2048
 
 ofp_port_features_map = {
-    1 << 0: 'OFPPF_10MB_HD',
-    1 << 1: 'OFPPF_10MB_FD',
-    1 << 2: 'OFPPF_100MB_HD',
-    1 << 3: 'OFPPF_100MB_FD',
-    1 << 4: 'OFPPF_1GB_HD',
-    1 << 5: 'OFPPF_1GB_FD',
-    1 << 6: 'OFPPF_10GB_FD',
-    1 << 7: 'OFPPF_COPPER',
-    1 << 8: 'OFPPF_FIBER',
-    1 << 9: 'OFPPF_AUTONEG',
-    1 << 10: 'OFPPF_PAUSE',
-    1 << 11: 'OFPPF_PAUSE_ASYM',
+    1: 'OFPPF_10MB_HD',
+    2: 'OFPPF_10MB_FD',
+    4: 'OFPPF_100MB_HD',
+    8: 'OFPPF_100MB_FD',
+    16: 'OFPPF_1GB_HD',
+    32: 'OFPPF_1GB_FD',
+    64: 'OFPPF_10GB_FD',
+    128: 'OFPPF_COPPER',
+    256: 'OFPPF_FIBER',
+    512: 'OFPPF_AUTONEG',
+    1024: 'OFPPF_PAUSE',
+    2048: 'OFPPF_PAUSE_ASYM',
 }
 
 # Identifiers from group ofp_port_mod_failed_code
@@ -363,20 +363,20 @@
 }
 
 # Identifiers from group ofp_port_state
-OFPPS_STP_LISTEN = 0 << 8
-OFPPS_LINK_DOWN = 1 << 0
-OFPPS_STP_LEARN = 1 << 8
-OFPPS_STP_FORWARD = 2 << 8
-OFPPS_STP_BLOCK = 3 << 8
-OFPPS_STP_MASK = 3 << 8
+OFPPS_STP_LISTEN = 0
+OFPPS_LINK_DOWN = 1
+OFPPS_STP_LEARN = 256
+OFPPS_STP_FORWARD = 512
+OFPPS_STP_BLOCK = 768
+OFPPS_STP_MASK = 768
 
 ofp_port_state_map = {
-    0 << 8: 'OFPPS_STP_LISTEN',
-    1 << 0: 'OFPPS_LINK_DOWN',
-    1 << 8: 'OFPPS_STP_LEARN',
-    2 << 8: 'OFPPS_STP_FORWARD',
-    3 << 8: 'OFPPS_STP_BLOCK',
-    3 << 8: 'OFPPS_STP_MASK',
+    0: 'OFPPS_STP_LISTEN',
+    1: 'OFPPS_LINK_DOWN',
+    256: 'OFPPS_STP_LEARN',
+    512: 'OFPPS_STP_FORWARD',
+    768: 'OFPPS_STP_BLOCK',
+    768: 'OFPPS_STP_MASK',
 }
 
 # Identifiers from group ofp_queue_op_failed_code
@@ -400,10 +400,10 @@
 }
 
 # Identifiers from group ofp_stats_reply_flags
-OFPSF_REPLY_MORE = 1 << 0
+OFPSF_REPLY_MORE = 1
 
 ofp_stats_reply_flags_map = {
-    1 << 0: 'OFPSF_REPLY_MORE',
+    1: 'OFPSF_REPLY_MORE',
 }
 
 # Identifiers from group ofp_stats_types
@@ -413,7 +413,7 @@
 OFPST_TABLE = 3
 OFPST_PORT = 4
 OFPST_QUEUE = 5
-OFPST_VENDOR = 0xffff
+OFPST_VENDOR = 65535
 
 ofp_stats_types_map = {
     0: 'OFPST_DESC',
@@ -422,7 +422,7 @@
     3: 'OFPST_TABLE',
     4: 'OFPST_PORT',
     5: 'OFPST_QUEUE',
-    0xffff: 'OFPST_VENDOR',
+    65535: 'OFPST_VENDOR',
 }
 
 # Identifiers from group ofp_type
diff --git a/src/python/loxi/of10/message.py b/src/python/loxi/of10/message.py
index d80dac3..f12fe1d 100644
--- a/src/python/loxi/of10/message.py
+++ b/src/python/loxi/of10/message.py
@@ -1,17 +1,6 @@
-#
-# Copyright 2012, 2013, Big Switch Networks, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
 
 # Automatically generated by LOXI from template message.py
 # Do not modify
@@ -22,6 +11,7 @@
 import common
 import action # for unpack_list
 import util
+import loxi.generic_util
 
 class Message(object):
     version = const.OFP_VERSION
@@ -33,7 +23,7 @@
     type = const.OFPT_STATS_REPLY
     stats_type = const.OFPST_AGGREGATE
 
-    def __init__(self, xid=None, flags=None, packet_count=None, byte_count=None, flow_count=None, pad=None):
+    def __init__(self, xid=None, flags=None, packet_count=None, byte_count=None, flow_count=None):
         self.xid = xid
         if flags != None:
             self.flags = flags
@@ -51,10 +41,6 @@
             self.flow_count = flow_count
         else:
             self.flow_count = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0,0,0]
 
     def pack(self):
         packed = []
@@ -67,7 +53,7 @@
         packed.append(struct.pack("!Q", self.packet_count))
         packed.append(struct.pack("!Q", self.byte_count))
         packed.append(struct.pack("!L", self.flow_count))
-        packed.append(struct.pack("!4B", *self.pad))
+        packed.append('\x00' * 4)
         length = sum([len(x) for x in packed])
         packed[2] = struct.pack("!H", length)
         return ''.join(packed)
@@ -76,21 +62,23 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = aggregate_stats_reply()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_STATS_REPLY)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 36: raise loxi.ProtocolError("aggregate_stats_reply length is %d, should be 36" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        stats_type = struct.unpack_from('!H', buf, 8)[0]
-        assert(stats_type == const.OFPST_AGGREGATE)
-        obj.flags = struct.unpack_from('!H', buf, 10)[0]
-        obj.packet_count = struct.unpack_from('!Q', buf, 12)[0]
-        obj.byte_count = struct.unpack_from('!Q', buf, 20)[0]
-        obj.flow_count = struct.unpack_from('!L', buf, 28)[0]
-        obj.pad = list(struct.unpack_from('!4B', buf, 32))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_AGGREGATE)
+        obj.flags = reader.read('!H')[0]
+        obj.packet_count = reader.read('!Q')[0]
+        obj.byte_count = reader.read('!Q')[0]
+        obj.flow_count = reader.read('!L')[0]
+        reader.skip(4)
         return obj
 
     def __eq__(self, other):
@@ -102,7 +90,6 @@
         if self.packet_count != other.packet_count: return False
         if self.byte_count != other.byte_count: return False
         if self.flow_count != other.flow_count: return False
-        if self.pad != other.pad: return False
         return True
 
     def __ne__(self, other):
@@ -137,9 +124,6 @@
                 q.text(","); q.breakable()
                 q.text("flow_count = ");
                 q.text("%#x" % self.flow_count)
-                q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
             q.breakable()
         q.text('}')
 
@@ -148,7 +132,7 @@
     type = const.OFPT_STATS_REQUEST
     stats_type = const.OFPST_AGGREGATE
 
-    def __init__(self, xid=None, flags=None, match=None, table_id=None, pad=None, out_port=None):
+    def __init__(self, xid=None, flags=None, match=None, table_id=None, out_port=None):
         self.xid = xid
         if flags != None:
             self.flags = flags
@@ -162,10 +146,6 @@
             self.table_id = table_id
         else:
             self.table_id = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = 0
         if out_port != None:
             self.out_port = out_port
         else:
@@ -181,7 +161,7 @@
         packed.append(struct.pack("!H", self.flags))
         packed.append(self.match.pack())
         packed.append(struct.pack("!B", self.table_id))
-        packed.append(struct.pack("!B", self.pad))
+        packed.append('\x00' * 1)
         packed.append(struct.pack("!H", self.out_port))
         length = sum([len(x) for x in packed])
         packed[2] = struct.pack("!H", length)
@@ -191,21 +171,23 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = aggregate_stats_request()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_STATS_REQUEST)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 56: raise loxi.ProtocolError("aggregate_stats_request length is %d, should be 56" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        stats_type = struct.unpack_from('!H', buf, 8)[0]
-        assert(stats_type == const.OFPST_AGGREGATE)
-        obj.flags = struct.unpack_from('!H', buf, 10)[0]
-        obj.match = common.match.unpack(buffer(buf, 12))
-        obj.table_id = struct.unpack_from('!B', buf, 52)[0]
-        obj.pad = struct.unpack_from('!B', buf, 53)[0]
-        obj.out_port = struct.unpack_from('!H', buf, 54)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_AGGREGATE)
+        obj.flags = reader.read('!H')[0]
+        obj.match = common.match.unpack(reader)
+        obj.table_id = reader.read('!B')[0]
+        reader.skip(1)
+        obj.out_port = reader.read('!H')[0]
         return obj
 
     def __eq__(self, other):
@@ -216,7 +198,6 @@
         if self.flags != other.flags: return False
         if self.match != other.match: return False
         if self.table_id != other.table_id: return False
-        if self.pad != other.pad: return False
         if self.out_port != other.out_port: return False
         return True
 
@@ -250,9 +231,6 @@
                 q.text("table_id = ");
                 q.text("%#x" % self.table_id)
                 q.text(","); q.breakable()
-                q.text("pad = ");
-                q.text("%#x" % self.pad)
-                q.text(","); q.breakable()
                 q.text("out_port = ");
                 q.text(util.pretty_port(self.out_port))
             q.breakable()
@@ -279,14 +257,16 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = barrier_reply()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_BARRIER_REPLY)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 8: raise loxi.ProtocolError("barrier_reply length is %d, should be 8" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_BARRIER_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
         return obj
 
     def __eq__(self, other):
@@ -340,14 +320,16 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = barrier_request()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_BARRIER_REQUEST)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 8: raise loxi.ProtocolError("barrier_request length is %d, should be 8" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_BARRIER_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
         return obj
 
     def __eq__(self, other):
@@ -410,19 +392,21 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = bsn_get_interfaces_reply()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_VENDOR)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length < 16: raise loxi.ProtocolError("bsn_get_interfaces_reply length is %d, should be at least 16" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        experimenter = struct.unpack_from('!L', buf, 8)[0]
-        assert(experimenter == 0x5c16c7)
-        subtype = struct.unpack_from('!L', buf, 12)[0]
-        assert(subtype == 10)
-        obj.interfaces = util.unpack_array(common.bsn_interface.unpack, 32, buffer(buf, 16))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_VENDOR)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 10)
+        obj.interfaces = loxi.generic_util.unpack_list(reader, common.bsn_interface.unpack)
         return obj
 
     def __eq__(self, other):
@@ -484,18 +468,20 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = bsn_get_interfaces_request()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_VENDOR)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 16: raise loxi.ProtocolError("bsn_get_interfaces_request length is %d, should be 16" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        experimenter = struct.unpack_from('!L', buf, 8)[0]
-        assert(experimenter == 0x5c16c7)
-        subtype = struct.unpack_from('!L', buf, 12)[0]
-        assert(subtype == 9)
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_VENDOR)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 9)
         return obj
 
     def __eq__(self, other):
@@ -534,16 +520,12 @@
     experimenter = 0x5c16c7
     subtype = 2
 
-    def __init__(self, xid=None, index=None, pad=None, mask=None):
+    def __init__(self, xid=None, index=None, mask=None):
         self.xid = xid
         if index != None:
             self.index = index
         else:
             self.index = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0,0]
         if mask != None:
             self.mask = mask
         else:
@@ -558,7 +540,7 @@
         packed.append(struct.pack("!L", self.experimenter))
         packed.append(struct.pack("!L", self.subtype))
         packed.append(struct.pack("!B", self.index))
-        packed.append(struct.pack("!3B", *self.pad))
+        packed.append('\x00' * 3)
         packed.append(struct.pack("!L", self.mask))
         length = sum([len(x) for x in packed])
         packed[2] = struct.pack("!H", length)
@@ -568,21 +550,23 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = bsn_get_ip_mask_reply()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_VENDOR)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 24: raise loxi.ProtocolError("bsn_get_ip_mask_reply length is %d, should be 24" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        experimenter = struct.unpack_from('!L', buf, 8)[0]
-        assert(experimenter == 0x5c16c7)
-        subtype = struct.unpack_from('!L', buf, 12)[0]
-        assert(subtype == 2)
-        obj.index = struct.unpack_from('!B', buf, 16)[0]
-        obj.pad = list(struct.unpack_from('!3B', buf, 17))
-        obj.mask = struct.unpack_from('!L', buf, 20)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_VENDOR)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 2)
+        obj.index = reader.read('!B')[0]
+        reader.skip(3)
+        obj.mask = reader.read('!L')[0]
         return obj
 
     def __eq__(self, other):
@@ -591,7 +575,6 @@
         if self.type != other.type: return False
         if self.xid != other.xid: return False
         if self.index != other.index: return False
-        if self.pad != other.pad: return False
         if self.mask != other.mask: return False
         return True
 
@@ -619,9 +602,6 @@
                 q.text("index = ");
                 q.text("%#x" % self.index)
                 q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
-                q.text(","); q.breakable()
                 q.text("mask = ");
                 q.text("%#x" % self.mask)
             q.breakable()
@@ -633,16 +613,12 @@
     experimenter = 0x5c16c7
     subtype = 1
 
-    def __init__(self, xid=None, index=None, pad=None):
+    def __init__(self, xid=None, index=None):
         self.xid = xid
         if index != None:
             self.index = index
         else:
             self.index = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0,0,0,0,0,0]
 
     def pack(self):
         packed = []
@@ -653,7 +629,7 @@
         packed.append(struct.pack("!L", self.experimenter))
         packed.append(struct.pack("!L", self.subtype))
         packed.append(struct.pack("!B", self.index))
-        packed.append(struct.pack("!7B", *self.pad))
+        packed.append('\x00' * 7)
         length = sum([len(x) for x in packed])
         packed[2] = struct.pack("!H", length)
         return ''.join(packed)
@@ -662,20 +638,22 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = bsn_get_ip_mask_request()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_VENDOR)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 24: raise loxi.ProtocolError("bsn_get_ip_mask_request length is %d, should be 24" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        experimenter = struct.unpack_from('!L', buf, 8)[0]
-        assert(experimenter == 0x5c16c7)
-        subtype = struct.unpack_from('!L', buf, 12)[0]
-        assert(subtype == 1)
-        obj.index = struct.unpack_from('!B', buf, 16)[0]
-        obj.pad = list(struct.unpack_from('!7B', buf, 17))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_VENDOR)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 1)
+        obj.index = reader.read('!B')[0]
+        reader.skip(7)
         return obj
 
     def __eq__(self, other):
@@ -684,7 +662,6 @@
         if self.type != other.type: return False
         if self.xid != other.xid: return False
         if self.index != other.index: return False
-        if self.pad != other.pad: return False
         return True
 
     def __ne__(self, other):
@@ -710,9 +687,6 @@
                 q.text(","); q.breakable()
                 q.text("index = ");
                 q.text("%#x" % self.index)
-                q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
             q.breakable()
         q.text('}')
 
@@ -722,16 +696,12 @@
     experimenter = 0x5c16c7
     subtype = 5
 
-    def __init__(self, xid=None, report_mirror_ports=None, pad=None):
+    def __init__(self, xid=None, report_mirror_ports=None):
         self.xid = xid
         if report_mirror_ports != None:
             self.report_mirror_ports = report_mirror_ports
         else:
             self.report_mirror_ports = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0,0]
 
     def pack(self):
         packed = []
@@ -742,7 +712,7 @@
         packed.append(struct.pack("!L", self.experimenter))
         packed.append(struct.pack("!L", self.subtype))
         packed.append(struct.pack("!B", self.report_mirror_ports))
-        packed.append(struct.pack("!3B", *self.pad))
+        packed.append('\x00' * 3)
         length = sum([len(x) for x in packed])
         packed[2] = struct.pack("!H", length)
         return ''.join(packed)
@@ -751,20 +721,22 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = bsn_get_mirroring_reply()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_VENDOR)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 20: raise loxi.ProtocolError("bsn_get_mirroring_reply length is %d, should be 20" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        experimenter = struct.unpack_from('!L', buf, 8)[0]
-        assert(experimenter == 0x5c16c7)
-        subtype = struct.unpack_from('!L', buf, 12)[0]
-        assert(subtype == 5)
-        obj.report_mirror_ports = struct.unpack_from('!B', buf, 16)[0]
-        obj.pad = list(struct.unpack_from('!3B', buf, 17))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_VENDOR)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 5)
+        obj.report_mirror_ports = reader.read('!B')[0]
+        reader.skip(3)
         return obj
 
     def __eq__(self, other):
@@ -773,7 +745,6 @@
         if self.type != other.type: return False
         if self.xid != other.xid: return False
         if self.report_mirror_ports != other.report_mirror_ports: return False
-        if self.pad != other.pad: return False
         return True
 
     def __ne__(self, other):
@@ -799,9 +770,6 @@
                 q.text(","); q.breakable()
                 q.text("report_mirror_ports = ");
                 q.text("%#x" % self.report_mirror_ports)
-                q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
             q.breakable()
         q.text('}')
 
@@ -811,16 +779,12 @@
     experimenter = 0x5c16c7
     subtype = 4
 
-    def __init__(self, xid=None, report_mirror_ports=None, pad=None):
+    def __init__(self, xid=None, report_mirror_ports=None):
         self.xid = xid
         if report_mirror_ports != None:
             self.report_mirror_ports = report_mirror_ports
         else:
             self.report_mirror_ports = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0,0]
 
     def pack(self):
         packed = []
@@ -831,7 +795,7 @@
         packed.append(struct.pack("!L", self.experimenter))
         packed.append(struct.pack("!L", self.subtype))
         packed.append(struct.pack("!B", self.report_mirror_ports))
-        packed.append(struct.pack("!3B", *self.pad))
+        packed.append('\x00' * 3)
         length = sum([len(x) for x in packed])
         packed[2] = struct.pack("!H", length)
         return ''.join(packed)
@@ -840,20 +804,22 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = bsn_get_mirroring_request()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_VENDOR)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 20: raise loxi.ProtocolError("bsn_get_mirroring_request length is %d, should be 20" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        experimenter = struct.unpack_from('!L', buf, 8)[0]
-        assert(experimenter == 0x5c16c7)
-        subtype = struct.unpack_from('!L', buf, 12)[0]
-        assert(subtype == 4)
-        obj.report_mirror_ports = struct.unpack_from('!B', buf, 16)[0]
-        obj.pad = list(struct.unpack_from('!3B', buf, 17))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_VENDOR)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 4)
+        obj.report_mirror_ports = reader.read('!B')[0]
+        reader.skip(3)
         return obj
 
     def __eq__(self, other):
@@ -862,7 +828,6 @@
         if self.type != other.type: return False
         if self.xid != other.xid: return False
         if self.report_mirror_ports != other.report_mirror_ports: return False
-        if self.pad != other.pad: return False
         return True
 
     def __ne__(self, other):
@@ -888,9 +853,6 @@
                 q.text(","); q.breakable()
                 q.text("report_mirror_ports = ");
                 q.text("%#x" % self.report_mirror_ports)
-                q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
             q.breakable()
         q.text('}')
 
@@ -900,16 +862,12 @@
     experimenter = 0x5c16c7
     subtype = 0
 
-    def __init__(self, xid=None, index=None, pad=None, mask=None):
+    def __init__(self, xid=None, index=None, mask=None):
         self.xid = xid
         if index != None:
             self.index = index
         else:
             self.index = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0,0]
         if mask != None:
             self.mask = mask
         else:
@@ -924,7 +882,7 @@
         packed.append(struct.pack("!L", self.experimenter))
         packed.append(struct.pack("!L", self.subtype))
         packed.append(struct.pack("!B", self.index))
-        packed.append(struct.pack("!3B", *self.pad))
+        packed.append('\x00' * 3)
         packed.append(struct.pack("!L", self.mask))
         length = sum([len(x) for x in packed])
         packed[2] = struct.pack("!H", length)
@@ -934,21 +892,23 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = bsn_set_ip_mask()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_VENDOR)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 24: raise loxi.ProtocolError("bsn_set_ip_mask length is %d, should be 24" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        experimenter = struct.unpack_from('!L', buf, 8)[0]
-        assert(experimenter == 0x5c16c7)
-        subtype = struct.unpack_from('!L', buf, 12)[0]
-        assert(subtype == 0)
-        obj.index = struct.unpack_from('!B', buf, 16)[0]
-        obj.pad = list(struct.unpack_from('!3B', buf, 17))
-        obj.mask = struct.unpack_from('!L', buf, 20)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_VENDOR)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 0)
+        obj.index = reader.read('!B')[0]
+        reader.skip(3)
+        obj.mask = reader.read('!L')[0]
         return obj
 
     def __eq__(self, other):
@@ -957,7 +917,6 @@
         if self.type != other.type: return False
         if self.xid != other.xid: return False
         if self.index != other.index: return False
-        if self.pad != other.pad: return False
         if self.mask != other.mask: return False
         return True
 
@@ -985,9 +944,6 @@
                 q.text("index = ");
                 q.text("%#x" % self.index)
                 q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
-                q.text(","); q.breakable()
                 q.text("mask = ");
                 q.text("%#x" % self.mask)
             q.breakable()
@@ -999,16 +955,12 @@
     experimenter = 0x5c16c7
     subtype = 3
 
-    def __init__(self, xid=None, report_mirror_ports=None, pad=None):
+    def __init__(self, xid=None, report_mirror_ports=None):
         self.xid = xid
         if report_mirror_ports != None:
             self.report_mirror_ports = report_mirror_ports
         else:
             self.report_mirror_ports = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0,0]
 
     def pack(self):
         packed = []
@@ -1019,7 +971,7 @@
         packed.append(struct.pack("!L", self.experimenter))
         packed.append(struct.pack("!L", self.subtype))
         packed.append(struct.pack("!B", self.report_mirror_ports))
-        packed.append(struct.pack("!3B", *self.pad))
+        packed.append('\x00' * 3)
         length = sum([len(x) for x in packed])
         packed[2] = struct.pack("!H", length)
         return ''.join(packed)
@@ -1028,20 +980,22 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = bsn_set_mirroring()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_VENDOR)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 20: raise loxi.ProtocolError("bsn_set_mirroring length is %d, should be 20" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        experimenter = struct.unpack_from('!L', buf, 8)[0]
-        assert(experimenter == 0x5c16c7)
-        subtype = struct.unpack_from('!L', buf, 12)[0]
-        assert(subtype == 3)
-        obj.report_mirror_ports = struct.unpack_from('!B', buf, 16)[0]
-        obj.pad = list(struct.unpack_from('!3B', buf, 17))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_VENDOR)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 3)
+        obj.report_mirror_ports = reader.read('!B')[0]
+        reader.skip(3)
         return obj
 
     def __eq__(self, other):
@@ -1050,7 +1004,6 @@
         if self.type != other.type: return False
         if self.xid != other.xid: return False
         if self.report_mirror_ports != other.report_mirror_ports: return False
-        if self.pad != other.pad: return False
         return True
 
     def __ne__(self, other):
@@ -1076,9 +1029,129 @@
                 q.text(","); q.breakable()
                 q.text("report_mirror_ports = ");
                 q.text("%#x" % self.report_mirror_ports)
+            q.breakable()
+        q.text('}')
+
+class bsn_set_pktin_suppression(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_VENDOR
+    experimenter = 0x5c16c7
+    subtype = 11
+
+    def __init__(self, xid=None, enabled=None, idle_timeout=None, hard_timeout=None, priority=None, cookie=None):
+        self.xid = xid
+        if enabled != None:
+            self.enabled = enabled
+        else:
+            self.enabled = 0
+        if idle_timeout != None:
+            self.idle_timeout = idle_timeout
+        else:
+            self.idle_timeout = 0
+        if hard_timeout != None:
+            self.hard_timeout = hard_timeout
+        else:
+            self.hard_timeout = 0
+        if priority != None:
+            self.priority = priority
+        else:
+            self.priority = 0
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        packed.append(struct.pack("!B", self.enabled))
+        packed.append('\x00' * 1)
+        packed.append(struct.pack("!H", self.idle_timeout))
+        packed.append(struct.pack("!H", self.hard_timeout))
+        packed.append(struct.pack("!H", self.priority))
+        packed.append(struct.pack("!Q", self.cookie))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = bsn_set_pktin_suppression()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_VENDOR)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 11)
+        obj.enabled = reader.read('!B')[0]
+        reader.skip(1)
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.cookie = reader.read('!Q')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.enabled != other.enabled: return False
+        if self.idle_timeout != other.idle_timeout: return False
+        if self.hard_timeout != other.hard_timeout: return False
+        if self.priority != other.priority: return False
+        if self.cookie != other.cookie: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_set_pktin_suppression {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
                 q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
+                q.text("enabled = ");
+                q.text("%#x" % self.enabled)
+                q.text(","); q.breakable()
+                q.text("idle_timeout = ");
+                q.text("%#x" % self.idle_timeout)
+                q.text(","); q.breakable()
+                q.text("hard_timeout = ");
+                q.text("%#x" % self.hard_timeout)
+                q.text(","); q.breakable()
+                q.text("priority = ");
+                q.text("%#x" % self.priority)
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
             q.breakable()
         q.text('}')
 
@@ -1117,20 +1190,22 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = bsn_shell_command()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_VENDOR)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length < 20: raise loxi.ProtocolError("bsn_shell_command length is %d, should be at least 20" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        experimenter = struct.unpack_from('!L', buf, 8)[0]
-        assert(experimenter == 0x5c16c7)
-        subtype = struct.unpack_from('!L', buf, 12)[0]
-        assert(subtype == 6)
-        obj.service = struct.unpack_from('!L', buf, 16)[0]
-        obj.data = buf[20:]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_VENDOR)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 6)
+        obj.service = reader.read('!L')[0]
+        obj.data = str(reader.read_all())
         return obj
 
     def __eq__(self, other):
@@ -1201,19 +1276,21 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = bsn_shell_output()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_VENDOR)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length < 16: raise loxi.ProtocolError("bsn_shell_output length is %d, should be at least 16" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        experimenter = struct.unpack_from('!L', buf, 8)[0]
-        assert(experimenter == 0x5c16c7)
-        subtype = struct.unpack_from('!L', buf, 12)[0]
-        assert(subtype == 7)
-        obj.data = buf[16:]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_VENDOR)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 7)
+        obj.data = str(reader.read_all())
         return obj
 
     def __eq__(self, other):
@@ -1280,19 +1357,21 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = bsn_shell_status()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_VENDOR)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 20: raise loxi.ProtocolError("bsn_shell_status length is %d, should be 20" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        experimenter = struct.unpack_from('!L', buf, 8)[0]
-        assert(experimenter == 0x5c16c7)
-        subtype = struct.unpack_from('!L', buf, 12)[0]
-        assert(subtype == 8)
-        obj.status = struct.unpack_from('!L', buf, 16)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_VENDOR)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 8)
+        obj.status = reader.read('!L')[0]
         return obj
 
     def __eq__(self, other):
@@ -1382,22 +1461,24 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = desc_stats_reply()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_STATS_REPLY)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 1068: raise loxi.ProtocolError("desc_stats_reply length is %d, should be 1068" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        stats_type = struct.unpack_from('!H', buf, 8)[0]
-        assert(stats_type == const.OFPST_DESC)
-        obj.flags = struct.unpack_from('!H', buf, 10)[0]
-        obj.mfr_desc = str(buffer(buf, 12, 256)).rstrip("\x00")
-        obj.hw_desc = str(buffer(buf, 268, 256)).rstrip("\x00")
-        obj.sw_desc = str(buffer(buf, 524, 256)).rstrip("\x00")
-        obj.serial_num = str(buffer(buf, 780, 32)).rstrip("\x00")
-        obj.dp_desc = str(buffer(buf, 812, 256)).rstrip("\x00")
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_DESC)
+        obj.flags = reader.read('!H')[0]
+        obj.mfr_desc = reader.read("!256s")[0].rstrip("\x00")
+        obj.hw_desc = reader.read("!256s")[0].rstrip("\x00")
+        obj.sw_desc = reader.read("!256s")[0].rstrip("\x00")
+        obj.serial_num = reader.read("!32s")[0].rstrip("\x00")
+        obj.dp_desc = reader.read("!256s")[0].rstrip("\x00")
         return obj
 
     def __eq__(self, other):
@@ -1482,17 +1563,19 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = desc_stats_request()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_STATS_REQUEST)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 12: raise loxi.ProtocolError("desc_stats_request length is %d, should be 12" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        stats_type = struct.unpack_from('!H', buf, 8)[0]
-        assert(stats_type == const.OFPST_DESC)
-        obj.flags = struct.unpack_from('!H', buf, 10)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_DESC)
+        obj.flags = reader.read('!H')[0]
         return obj
 
     def __eq__(self, other):
@@ -1555,15 +1638,17 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = echo_reply()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_ECHO_REPLY)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length < 8: raise loxi.ProtocolError("echo_reply length is %d, should be at least 8" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        obj.data = buf[8:]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_ECHO_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.data = str(reader.read_all())
         return obj
 
     def __eq__(self, other):
@@ -1626,15 +1711,17 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = echo_request()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_ECHO_REQUEST)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length < 8: raise loxi.ProtocolError("echo_request length is %d, should be at least 8" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        obj.data = buf[8:]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_ECHO_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.data = str(reader.read_all())
         return obj
 
     def __eq__(self, other):
@@ -1707,17 +1794,19 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = error_msg()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_ERROR)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length < 12: raise loxi.ProtocolError("error_msg length is %d, should be at least 12" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        obj.err_type = struct.unpack_from('!H', buf, 8)[0]
-        obj.code = struct.unpack_from('!H', buf, 10)[0]
-        obj.data = buf[12:]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_ERROR)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.err_type = reader.read('!H')[0]
+        obj.code = reader.read('!H')[0]
+        obj.data = str(reader.read_all())
         return obj
 
     def __eq__(self, other):
@@ -1800,19 +1889,21 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = experimenter_stats_reply()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_STATS_REPLY)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length < 16: raise loxi.ProtocolError("experimenter_stats_reply length is %d, should be at least 16" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        stats_type = struct.unpack_from('!H', buf, 8)[0]
-        assert(stats_type == const.OFPST_VENDOR)
-        obj.flags = struct.unpack_from('!H', buf, 10)[0]
-        obj.experimenter = struct.unpack_from('!L', buf, 12)[0]
-        obj.data = buf[16:]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_VENDOR)
+        obj.flags = reader.read('!H')[0]
+        obj.experimenter = reader.read('!L')[0]
+        obj.data = str(reader.read_all())
         return obj
 
     def __eq__(self, other):
@@ -1895,19 +1986,21 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = experimenter_stats_request()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_STATS_REQUEST)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length < 16: raise loxi.ProtocolError("experimenter_stats_request length is %d, should be at least 16" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        stats_type = struct.unpack_from('!H', buf, 8)[0]
-        assert(stats_type == const.OFPST_VENDOR)
-        obj.flags = struct.unpack_from('!H', buf, 10)[0]
-        obj.experimenter = struct.unpack_from('!L', buf, 12)[0]
-        obj.data = buf[16:]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_VENDOR)
+        obj.flags = reader.read('!H')[0]
+        obj.experimenter = reader.read('!L')[0]
+        obj.data = str(reader.read_all())
         return obj
 
     def __eq__(self, other):
@@ -1956,7 +2049,7 @@
     version = const.OFP_VERSION
     type = const.OFPT_FEATURES_REPLY
 
-    def __init__(self, xid=None, datapath_id=None, n_buffers=None, n_tables=None, pad=None, capabilities=None, actions=None, ports=None):
+    def __init__(self, xid=None, datapath_id=None, n_buffers=None, n_tables=None, capabilities=None, actions=None, ports=None):
         self.xid = xid
         if datapath_id != None:
             self.datapath_id = datapath_id
@@ -1970,10 +2063,6 @@
             self.n_tables = n_tables
         else:
             self.n_tables = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0,0]
         if capabilities != None:
             self.capabilities = capabilities
         else:
@@ -1996,7 +2085,7 @@
         packed.append(struct.pack("!Q", self.datapath_id))
         packed.append(struct.pack("!L", self.n_buffers))
         packed.append(struct.pack("!B", self.n_tables))
-        packed.append(struct.pack("!3B", *self.pad))
+        packed.append('\x00' * 3)
         packed.append(struct.pack("!L", self.capabilities))
         packed.append(struct.pack("!L", self.actions))
         packed.append("".join([x.pack() for x in self.ports]))
@@ -2008,21 +2097,23 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = features_reply()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_FEATURES_REPLY)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length < 32: raise loxi.ProtocolError("features_reply length is %d, should be at least 32" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        obj.datapath_id = struct.unpack_from('!Q', buf, 8)[0]
-        obj.n_buffers = struct.unpack_from('!L', buf, 16)[0]
-        obj.n_tables = struct.unpack_from('!B', buf, 20)[0]
-        obj.pad = list(struct.unpack_from('!3B', buf, 21))
-        obj.capabilities = struct.unpack_from('!L', buf, 24)[0]
-        obj.actions = struct.unpack_from('!L', buf, 28)[0]
-        obj.ports = util.unpack_array(common.port_desc.unpack, 48, buffer(buf, 32))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FEATURES_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.datapath_id = reader.read('!Q')[0]
+        obj.n_buffers = reader.read('!L')[0]
+        obj.n_tables = reader.read('!B')[0]
+        reader.skip(3)
+        obj.capabilities = reader.read('!L')[0]
+        obj.actions = reader.read('!L')[0]
+        obj.ports = loxi.generic_util.unpack_list(reader, common.port_desc.unpack)
         return obj
 
     def __eq__(self, other):
@@ -2033,7 +2124,6 @@
         if self.datapath_id != other.datapath_id: return False
         if self.n_buffers != other.n_buffers: return False
         if self.n_tables != other.n_tables: return False
-        if self.pad != other.pad: return False
         if self.capabilities != other.capabilities: return False
         if self.actions != other.actions: return False
         if self.ports != other.ports: return False
@@ -2069,9 +2159,6 @@
                 q.text("n_tables = ");
                 q.text("%#x" % self.n_tables)
                 q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
-                q.text(","); q.breakable()
                 q.text("capabilities = ");
                 q.text("%#x" % self.capabilities)
                 q.text(","); q.breakable()
@@ -2104,14 +2191,16 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = features_request()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_FEATURES_REQUEST)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 8: raise loxi.ProtocolError("features_request length is %d, should be 8" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FEATURES_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
         return obj
 
     def __eq__(self, other):
@@ -2212,25 +2301,27 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = flow_add()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_FLOW_MOD)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length < 72: raise loxi.ProtocolError("flow_add length is %d, should be at least 72" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        obj.match = common.match.unpack(buffer(buf, 8))
-        obj.cookie = struct.unpack_from('!Q', buf, 48)[0]
-        _command = struct.unpack_from('!H', buf, 56)[0]
-        assert(_command == const.OFPFC_ADD)
-        obj.idle_timeout = struct.unpack_from('!H', buf, 58)[0]
-        obj.hard_timeout = struct.unpack_from('!H', buf, 60)[0]
-        obj.priority = struct.unpack_from('!H', buf, 62)[0]
-        obj.buffer_id = struct.unpack_from('!L', buf, 64)[0]
-        obj.out_port = struct.unpack_from('!H', buf, 68)[0]
-        obj.flags = struct.unpack_from('!H', buf, 70)[0]
-        obj.actions = action.unpack_list(buffer(buf, 72))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FLOW_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.match = common.match.unpack(reader)
+        obj.cookie = reader.read('!Q')[0]
+        __command = reader.read('!H')[0]
+        assert(__command == const.OFPFC_ADD)
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.out_port = reader.read('!H')[0]
+        obj.flags = reader.read('!H')[0]
+        obj.actions = action.unpack_list(reader)
         return obj
 
     def __eq__(self, other):
@@ -2367,25 +2458,27 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = flow_delete()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_FLOW_MOD)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length < 72: raise loxi.ProtocolError("flow_delete length is %d, should be at least 72" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        obj.match = common.match.unpack(buffer(buf, 8))
-        obj.cookie = struct.unpack_from('!Q', buf, 48)[0]
-        _command = struct.unpack_from('!H', buf, 56)[0]
-        assert(_command == const.OFPFC_DELETE)
-        obj.idle_timeout = struct.unpack_from('!H', buf, 58)[0]
-        obj.hard_timeout = struct.unpack_from('!H', buf, 60)[0]
-        obj.priority = struct.unpack_from('!H', buf, 62)[0]
-        obj.buffer_id = struct.unpack_from('!L', buf, 64)[0]
-        obj.out_port = struct.unpack_from('!H', buf, 68)[0]
-        obj.flags = struct.unpack_from('!H', buf, 70)[0]
-        obj.actions = action.unpack_list(buffer(buf, 72))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FLOW_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.match = common.match.unpack(reader)
+        obj.cookie = reader.read('!Q')[0]
+        __command = reader.read('!H')[0]
+        assert(__command == const.OFPFC_DELETE)
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.out_port = reader.read('!H')[0]
+        obj.flags = reader.read('!H')[0]
+        obj.actions = action.unpack_list(reader)
         return obj
 
     def __eq__(self, other):
@@ -2522,25 +2615,27 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = flow_delete_strict()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_FLOW_MOD)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length < 72: raise loxi.ProtocolError("flow_delete_strict length is %d, should be at least 72" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        obj.match = common.match.unpack(buffer(buf, 8))
-        obj.cookie = struct.unpack_from('!Q', buf, 48)[0]
-        _command = struct.unpack_from('!H', buf, 56)[0]
-        assert(_command == const.OFPFC_DELETE_STRICT)
-        obj.idle_timeout = struct.unpack_from('!H', buf, 58)[0]
-        obj.hard_timeout = struct.unpack_from('!H', buf, 60)[0]
-        obj.priority = struct.unpack_from('!H', buf, 62)[0]
-        obj.buffer_id = struct.unpack_from('!L', buf, 64)[0]
-        obj.out_port = struct.unpack_from('!H', buf, 68)[0]
-        obj.flags = struct.unpack_from('!H', buf, 70)[0]
-        obj.actions = action.unpack_list(buffer(buf, 72))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FLOW_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.match = common.match.unpack(reader)
+        obj.cookie = reader.read('!Q')[0]
+        __command = reader.read('!H')[0]
+        assert(__command == const.OFPFC_DELETE_STRICT)
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.out_port = reader.read('!H')[0]
+        obj.flags = reader.read('!H')[0]
+        obj.actions = action.unpack_list(reader)
         return obj
 
     def __eq__(self, other):
@@ -2677,25 +2772,27 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = flow_modify()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_FLOW_MOD)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length < 72: raise loxi.ProtocolError("flow_modify length is %d, should be at least 72" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        obj.match = common.match.unpack(buffer(buf, 8))
-        obj.cookie = struct.unpack_from('!Q', buf, 48)[0]
-        _command = struct.unpack_from('!H', buf, 56)[0]
-        assert(_command == const.OFPFC_MODIFY)
-        obj.idle_timeout = struct.unpack_from('!H', buf, 58)[0]
-        obj.hard_timeout = struct.unpack_from('!H', buf, 60)[0]
-        obj.priority = struct.unpack_from('!H', buf, 62)[0]
-        obj.buffer_id = struct.unpack_from('!L', buf, 64)[0]
-        obj.out_port = struct.unpack_from('!H', buf, 68)[0]
-        obj.flags = struct.unpack_from('!H', buf, 70)[0]
-        obj.actions = action.unpack_list(buffer(buf, 72))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FLOW_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.match = common.match.unpack(reader)
+        obj.cookie = reader.read('!Q')[0]
+        __command = reader.read('!H')[0]
+        assert(__command == const.OFPFC_MODIFY)
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.out_port = reader.read('!H')[0]
+        obj.flags = reader.read('!H')[0]
+        obj.actions = action.unpack_list(reader)
         return obj
 
     def __eq__(self, other):
@@ -2832,25 +2929,27 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = flow_modify_strict()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_FLOW_MOD)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length < 72: raise loxi.ProtocolError("flow_modify_strict length is %d, should be at least 72" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        obj.match = common.match.unpack(buffer(buf, 8))
-        obj.cookie = struct.unpack_from('!Q', buf, 48)[0]
-        _command = struct.unpack_from('!H', buf, 56)[0]
-        assert(_command == const.OFPFC_MODIFY_STRICT)
-        obj.idle_timeout = struct.unpack_from('!H', buf, 58)[0]
-        obj.hard_timeout = struct.unpack_from('!H', buf, 60)[0]
-        obj.priority = struct.unpack_from('!H', buf, 62)[0]
-        obj.buffer_id = struct.unpack_from('!L', buf, 64)[0]
-        obj.out_port = struct.unpack_from('!H', buf, 68)[0]
-        obj.flags = struct.unpack_from('!H', buf, 70)[0]
-        obj.actions = action.unpack_list(buffer(buf, 72))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FLOW_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.match = common.match.unpack(reader)
+        obj.cookie = reader.read('!Q')[0]
+        __command = reader.read('!H')[0]
+        assert(__command == const.OFPFC_MODIFY_STRICT)
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.out_port = reader.read('!H')[0]
+        obj.flags = reader.read('!H')[0]
+        obj.actions = action.unpack_list(reader)
         return obj
 
     def __eq__(self, other):
@@ -2923,7 +3022,7 @@
     version = const.OFP_VERSION
     type = const.OFPT_FLOW_REMOVED
 
-    def __init__(self, xid=None, match=None, cookie=None, priority=None, reason=None, pad=None, duration_sec=None, duration_nsec=None, idle_timeout=None, pad2=None, packet_count=None, byte_count=None):
+    def __init__(self, xid=None, match=None, cookie=None, priority=None, reason=None, duration_sec=None, duration_nsec=None, idle_timeout=None, packet_count=None, byte_count=None):
         self.xid = xid
         if match != None:
             self.match = match
@@ -2941,10 +3040,6 @@
             self.reason = reason
         else:
             self.reason = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = 0
         if duration_sec != None:
             self.duration_sec = duration_sec
         else:
@@ -2957,10 +3052,6 @@
             self.idle_timeout = idle_timeout
         else:
             self.idle_timeout = 0
-        if pad2 != None:
-            self.pad2 = pad2
-        else:
-            self.pad2 = [0,0]
         if packet_count != None:
             self.packet_count = packet_count
         else:
@@ -2980,11 +3071,11 @@
         packed.append(struct.pack("!Q", self.cookie))
         packed.append(struct.pack("!H", self.priority))
         packed.append(struct.pack("!B", self.reason))
-        packed.append(struct.pack("!B", self.pad))
+        packed.append('\x00' * 1)
         packed.append(struct.pack("!L", self.duration_sec))
         packed.append(struct.pack("!L", self.duration_nsec))
         packed.append(struct.pack("!H", self.idle_timeout))
-        packed.append(struct.pack("!2B", *self.pad2))
+        packed.append('\x00' * 2)
         packed.append(struct.pack("!Q", self.packet_count))
         packed.append(struct.pack("!Q", self.byte_count))
         length = sum([len(x) for x in packed])
@@ -2995,25 +3086,27 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = flow_removed()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_FLOW_REMOVED)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 88: raise loxi.ProtocolError("flow_removed length is %d, should be 88" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        obj.match = common.match.unpack(buffer(buf, 8))
-        obj.cookie = struct.unpack_from('!Q', buf, 48)[0]
-        obj.priority = struct.unpack_from('!H', buf, 56)[0]
-        obj.reason = struct.unpack_from('!B', buf, 58)[0]
-        obj.pad = struct.unpack_from('!B', buf, 59)[0]
-        obj.duration_sec = struct.unpack_from('!L', buf, 60)[0]
-        obj.duration_nsec = struct.unpack_from('!L', buf, 64)[0]
-        obj.idle_timeout = struct.unpack_from('!H', buf, 68)[0]
-        obj.pad2 = list(struct.unpack_from('!2B', buf, 70))
-        obj.packet_count = struct.unpack_from('!Q', buf, 72)[0]
-        obj.byte_count = struct.unpack_from('!Q', buf, 80)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FLOW_REMOVED)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.match = common.match.unpack(reader)
+        obj.cookie = reader.read('!Q')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.reason = reader.read('!B')[0]
+        reader.skip(1)
+        obj.duration_sec = reader.read('!L')[0]
+        obj.duration_nsec = reader.read('!L')[0]
+        obj.idle_timeout = reader.read('!H')[0]
+        reader.skip(2)
+        obj.packet_count = reader.read('!Q')[0]
+        obj.byte_count = reader.read('!Q')[0]
         return obj
 
     def __eq__(self, other):
@@ -3025,11 +3118,9 @@
         if self.cookie != other.cookie: return False
         if self.priority != other.priority: return False
         if self.reason != other.reason: return False
-        if self.pad != other.pad: return False
         if self.duration_sec != other.duration_sec: return False
         if self.duration_nsec != other.duration_nsec: return False
         if self.idle_timeout != other.idle_timeout: return False
-        if self.pad2 != other.pad2: return False
         if self.packet_count != other.packet_count: return False
         if self.byte_count != other.byte_count: return False
         return True
@@ -3067,9 +3158,6 @@
                 q.text("reason = ");
                 q.text("%#x" % self.reason)
                 q.text(","); q.breakable()
-                q.text("pad = ");
-                q.text("%#x" % self.pad)
-                q.text(","); q.breakable()
                 q.text("duration_sec = ");
                 q.text("%#x" % self.duration_sec)
                 q.text(","); q.breakable()
@@ -3079,9 +3167,6 @@
                 q.text("idle_timeout = ");
                 q.text("%#x" % self.idle_timeout)
                 q.text(","); q.breakable()
-                q.text("pad2 = ");
-                q.pp(self.pad2)
-                q.text(","); q.breakable()
                 q.text("packet_count = ");
                 q.text("%#x" % self.packet_count)
                 q.text(","); q.breakable()
@@ -3123,18 +3208,20 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = flow_stats_reply()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_STATS_REPLY)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length < 12: raise loxi.ProtocolError("flow_stats_reply length is %d, should be at least 12" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        stats_type = struct.unpack_from('!H', buf, 8)[0]
-        assert(stats_type == const.OFPST_FLOW)
-        obj.flags = struct.unpack_from('!H', buf, 10)[0]
-        obj.entries = common.unpack_list_flow_stats_entry(buffer(buf, 12))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_FLOW)
+        obj.flags = reader.read('!H')[0]
+        obj.entries = common.unpack_list_flow_stats_entry(reader)
         return obj
 
     def __eq__(self, other):
@@ -3180,7 +3267,7 @@
     type = const.OFPT_STATS_REQUEST
     stats_type = const.OFPST_FLOW
 
-    def __init__(self, xid=None, flags=None, match=None, table_id=None, pad=None, out_port=None):
+    def __init__(self, xid=None, flags=None, match=None, table_id=None, out_port=None):
         self.xid = xid
         if flags != None:
             self.flags = flags
@@ -3194,10 +3281,6 @@
             self.table_id = table_id
         else:
             self.table_id = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = 0
         if out_port != None:
             self.out_port = out_port
         else:
@@ -3213,7 +3296,7 @@
         packed.append(struct.pack("!H", self.flags))
         packed.append(self.match.pack())
         packed.append(struct.pack("!B", self.table_id))
-        packed.append(struct.pack("!B", self.pad))
+        packed.append('\x00' * 1)
         packed.append(struct.pack("!H", self.out_port))
         length = sum([len(x) for x in packed])
         packed[2] = struct.pack("!H", length)
@@ -3223,21 +3306,23 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = flow_stats_request()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_STATS_REQUEST)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 56: raise loxi.ProtocolError("flow_stats_request length is %d, should be 56" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        stats_type = struct.unpack_from('!H', buf, 8)[0]
-        assert(stats_type == const.OFPST_FLOW)
-        obj.flags = struct.unpack_from('!H', buf, 10)[0]
-        obj.match = common.match.unpack(buffer(buf, 12))
-        obj.table_id = struct.unpack_from('!B', buf, 52)[0]
-        obj.pad = struct.unpack_from('!B', buf, 53)[0]
-        obj.out_port = struct.unpack_from('!H', buf, 54)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_FLOW)
+        obj.flags = reader.read('!H')[0]
+        obj.match = common.match.unpack(reader)
+        obj.table_id = reader.read('!B')[0]
+        reader.skip(1)
+        obj.out_port = reader.read('!H')[0]
         return obj
 
     def __eq__(self, other):
@@ -3248,7 +3333,6 @@
         if self.flags != other.flags: return False
         if self.match != other.match: return False
         if self.table_id != other.table_id: return False
-        if self.pad != other.pad: return False
         if self.out_port != other.out_port: return False
         return True
 
@@ -3282,9 +3366,6 @@
                 q.text("table_id = ");
                 q.text("%#x" % self.table_id)
                 q.text(","); q.breakable()
-                q.text("pad = ");
-                q.text("%#x" % self.pad)
-                q.text(","); q.breakable()
                 q.text("out_port = ");
                 q.text(util.pretty_port(self.out_port))
             q.breakable()
@@ -3321,16 +3402,18 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = get_config_reply()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_GET_CONFIG_REPLY)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 12: raise loxi.ProtocolError("get_config_reply length is %d, should be 12" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        obj.flags = struct.unpack_from('!H', buf, 8)[0]
-        obj.miss_send_len = struct.unpack_from('!H', buf, 10)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_GET_CONFIG_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.flags = reader.read('!H')[0]
+        obj.miss_send_len = reader.read('!H')[0]
         return obj
 
     def __eq__(self, other):
@@ -3392,14 +3475,16 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = get_config_request()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_GET_CONFIG_REQUEST)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 8: raise loxi.ProtocolError("get_config_request length is %d, should be 8" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_GET_CONFIG_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
         return obj
 
     def __eq__(self, other):
@@ -3453,14 +3538,16 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = hello()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_HELLO)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 8: raise loxi.ProtocolError("hello length is %d, should be 8" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_HELLO)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
         return obj
 
     def __eq__(self, other):
@@ -3523,19 +3610,21 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = nicira_controller_role_reply()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_VENDOR)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 20: raise loxi.ProtocolError("nicira_controller_role_reply length is %d, should be 20" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        experimenter = struct.unpack_from('!L', buf, 8)[0]
-        assert(experimenter == 0x2320)
-        subtype = struct.unpack_from('!L', buf, 12)[0]
-        assert(subtype == 11)
-        obj.role = struct.unpack_from('!L', buf, 16)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_VENDOR)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x2320)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 11)
+        obj.role = reader.read('!L')[0]
         return obj
 
     def __eq__(self, other):
@@ -3602,19 +3691,21 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = nicira_controller_role_request()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_VENDOR)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 20: raise loxi.ProtocolError("nicira_controller_role_request length is %d, should be 20" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        experimenter = struct.unpack_from('!L', buf, 8)[0]
-        assert(experimenter == 0x2320)
-        subtype = struct.unpack_from('!L', buf, 12)[0]
-        assert(subtype == 10)
-        obj.role = struct.unpack_from('!L', buf, 16)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_VENDOR)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x2320)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 10)
+        obj.role = reader.read('!L')[0]
         return obj
 
     def __eq__(self, other):
@@ -3655,7 +3746,7 @@
     version = const.OFP_VERSION
     type = const.OFPT_PACKET_IN
 
-    def __init__(self, xid=None, buffer_id=None, total_len=None, in_port=None, reason=None, pad=None, data=None):
+    def __init__(self, xid=None, buffer_id=None, total_len=None, in_port=None, reason=None, data=None):
         self.xid = xid
         if buffer_id != None:
             self.buffer_id = buffer_id
@@ -3673,10 +3764,6 @@
             self.reason = reason
         else:
             self.reason = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = 0
         if data != None:
             self.data = data
         else:
@@ -3692,7 +3779,7 @@
         packed.append(struct.pack("!H", self.total_len))
         packed.append(struct.pack("!H", self.in_port))
         packed.append(struct.pack("!B", self.reason))
-        packed.append(struct.pack("!B", self.pad))
+        packed.append('\x00' * 1)
         packed.append(self.data)
         length = sum([len(x) for x in packed])
         packed[2] = struct.pack("!H", length)
@@ -3702,20 +3789,22 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = packet_in()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_PACKET_IN)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length < 18: raise loxi.ProtocolError("packet_in length is %d, should be at least 18" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        obj.buffer_id = struct.unpack_from('!L', buf, 8)[0]
-        obj.total_len = struct.unpack_from('!H', buf, 12)[0]
-        obj.in_port = struct.unpack_from('!H', buf, 14)[0]
-        obj.reason = struct.unpack_from('!B', buf, 16)[0]
-        obj.pad = struct.unpack_from('!B', buf, 17)[0]
-        obj.data = buf[18:]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_PACKET_IN)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.total_len = reader.read('!H')[0]
+        obj.in_port = reader.read('!H')[0]
+        obj.reason = reader.read('!B')[0]
+        reader.skip(1)
+        obj.data = str(reader.read_all())
         return obj
 
     def __eq__(self, other):
@@ -3727,7 +3816,6 @@
         if self.total_len != other.total_len: return False
         if self.in_port != other.in_port: return False
         if self.reason != other.reason: return False
-        if self.pad != other.pad: return False
         if self.data != other.data: return False
         return True
 
@@ -3764,9 +3852,6 @@
                 q.text("reason = ");
                 q.text("%#x" % self.reason)
                 q.text(","); q.breakable()
-                q.text("pad = ");
-                q.text("%#x" % self.pad)
-                q.text(","); q.breakable()
                 q.text("data = ");
                 q.pp(self.data)
             q.breakable()
@@ -3799,13 +3884,13 @@
         packed = []
         packed.append(struct.pack("!B", self.version))
         packed.append(struct.pack("!B", self.type))
-        packed.append(struct.pack("!H", 0)) # placeholder for length at index 3
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
         packed.append(struct.pack("!L", self.xid))
         packed.append(struct.pack("!L", self.buffer_id))
         packed.append(struct.pack("!H", self.in_port))
-        packed_actions = "".join([x.pack() for x in self.actions])
-        packed.append(struct.pack("!H", len(packed_actions)))
-        packed.append(packed_actions)
+        packed.append(struct.pack("!H", 0)) # placeholder for actions_len at index 6
+        packed.append("".join([x.pack() for x in self.actions]))
+        packed[6] = struct.pack("!H", len(packed[-1]))
         packed.append(self.data)
         length = sum([len(x) for x in packed])
         packed[2] = struct.pack("!H", length)
@@ -3815,19 +3900,21 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = packet_out()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_PACKET_OUT)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length < 16: raise loxi.ProtocolError("packet_out length is %d, should be at least 16" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        obj.buffer_id = struct.unpack_from('!L', buf, 8)[0]
-        obj.in_port = struct.unpack_from('!H', buf, 12)[0]
-        actions_len = struct.unpack_from('!H', buf, 14)[0]
-        obj.actions = action.unpack_list(buffer(buf, 16, actions_len))
-        obj.data = str(buffer(buf, 16+actions_len))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_PACKET_OUT)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.in_port = reader.read('!H')[0]
+        _actions_len = reader.read('!H')[0]
+        obj.actions = action.unpack_list(reader.slice(_actions_len))
+        obj.data = str(reader.read_all())
         return obj
 
     def __eq__(self, other):
@@ -3880,7 +3967,7 @@
     version = const.OFP_VERSION
     type = const.OFPT_PORT_MOD
 
-    def __init__(self, xid=None, port_no=None, hw_addr=None, config=None, mask=None, advertise=None, pad=None):
+    def __init__(self, xid=None, port_no=None, hw_addr=None, config=None, mask=None, advertise=None):
         self.xid = xid
         if port_no != None:
             self.port_no = port_no
@@ -3902,10 +3989,6 @@
             self.advertise = advertise
         else:
             self.advertise = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0,0,0]
 
     def pack(self):
         packed = []
@@ -3918,7 +4001,7 @@
         packed.append(struct.pack("!L", self.config))
         packed.append(struct.pack("!L", self.mask))
         packed.append(struct.pack("!L", self.advertise))
-        packed.append(struct.pack("!4B", *self.pad))
+        packed.append('\x00' * 4)
         length = sum([len(x) for x in packed])
         packed[2] = struct.pack("!H", length)
         return ''.join(packed)
@@ -3927,20 +4010,22 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = port_mod()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_PORT_MOD)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 32: raise loxi.ProtocolError("port_mod length is %d, should be 32" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        obj.port_no = struct.unpack_from('!H', buf, 8)[0]
-        obj.hw_addr = list(struct.unpack_from('!6B', buf, 10))
-        obj.config = struct.unpack_from('!L', buf, 16)[0]
-        obj.mask = struct.unpack_from('!L', buf, 20)[0]
-        obj.advertise = struct.unpack_from('!L', buf, 24)[0]
-        obj.pad = list(struct.unpack_from('!4B', buf, 28))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_PORT_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.port_no = reader.read('!H')[0]
+        obj.hw_addr = list(reader.read('!6B'))
+        obj.config = reader.read('!L')[0]
+        obj.mask = reader.read('!L')[0]
+        obj.advertise = reader.read('!L')[0]
+        reader.skip(4)
         return obj
 
     def __eq__(self, other):
@@ -3953,7 +4038,6 @@
         if self.config != other.config: return False
         if self.mask != other.mask: return False
         if self.advertise != other.advertise: return False
-        if self.pad != other.pad: return False
         return True
 
     def __ne__(self, other):
@@ -3991,9 +4075,6 @@
                 q.text(","); q.breakable()
                 q.text("advertise = ");
                 q.text("%#x" % self.advertise)
-                q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
             q.breakable()
         q.text('}')
 
@@ -4030,18 +4111,20 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = port_stats_reply()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_STATS_REPLY)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length < 12: raise loxi.ProtocolError("port_stats_reply length is %d, should be at least 12" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        stats_type = struct.unpack_from('!H', buf, 8)[0]
-        assert(stats_type == const.OFPST_PORT)
-        obj.flags = struct.unpack_from('!H', buf, 10)[0]
-        obj.entries = util.unpack_array(common.port_stats_entry.unpack, 104, buffer(buf, 12))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_PORT)
+        obj.flags = reader.read('!H')[0]
+        obj.entries = loxi.generic_util.unpack_list(reader, common.port_stats_entry.unpack)
         return obj
 
     def __eq__(self, other):
@@ -4087,7 +4170,7 @@
     type = const.OFPT_STATS_REQUEST
     stats_type = const.OFPST_PORT
 
-    def __init__(self, xid=None, flags=None, port_no=None, pad=None):
+    def __init__(self, xid=None, flags=None, port_no=None):
         self.xid = xid
         if flags != None:
             self.flags = flags
@@ -4097,10 +4180,6 @@
             self.port_no = port_no
         else:
             self.port_no = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0,0,0,0,0]
 
     def pack(self):
         packed = []
@@ -4111,7 +4190,7 @@
         packed.append(struct.pack("!H", self.stats_type))
         packed.append(struct.pack("!H", self.flags))
         packed.append(struct.pack("!H", self.port_no))
-        packed.append(struct.pack("!6B", *self.pad))
+        packed.append('\x00' * 6)
         length = sum([len(x) for x in packed])
         packed[2] = struct.pack("!H", length)
         return ''.join(packed)
@@ -4120,19 +4199,21 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = port_stats_request()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_STATS_REQUEST)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 20: raise loxi.ProtocolError("port_stats_request length is %d, should be 20" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        stats_type = struct.unpack_from('!H', buf, 8)[0]
-        assert(stats_type == const.OFPST_PORT)
-        obj.flags = struct.unpack_from('!H', buf, 10)[0]
-        obj.port_no = struct.unpack_from('!H', buf, 12)[0]
-        obj.pad = list(struct.unpack_from('!6B', buf, 14))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_PORT)
+        obj.flags = reader.read('!H')[0]
+        obj.port_no = reader.read('!H')[0]
+        reader.skip(6)
         return obj
 
     def __eq__(self, other):
@@ -4142,7 +4223,6 @@
         if self.xid != other.xid: return False
         if self.flags != other.flags: return False
         if self.port_no != other.port_no: return False
-        if self.pad != other.pad: return False
         return True
 
     def __ne__(self, other):
@@ -4171,9 +4251,6 @@
                 q.text(","); q.breakable()
                 q.text("port_no = ");
                 q.text(util.pretty_port(self.port_no))
-                q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
             q.breakable()
         q.text('}')
 
@@ -4181,16 +4258,12 @@
     version = const.OFP_VERSION
     type = const.OFPT_PORT_STATUS
 
-    def __init__(self, xid=None, reason=None, pad=None, desc=None):
+    def __init__(self, xid=None, reason=None, desc=None):
         self.xid = xid
         if reason != None:
             self.reason = reason
         else:
             self.reason = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0,0,0,0,0,0]
         if desc != None:
             self.desc = desc
         else:
@@ -4203,7 +4276,7 @@
         packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
         packed.append(struct.pack("!L", self.xid))
         packed.append(struct.pack("!B", self.reason))
-        packed.append(struct.pack("!7B", *self.pad))
+        packed.append('\x00' * 7)
         packed.append(self.desc.pack())
         length = sum([len(x) for x in packed])
         packed[2] = struct.pack("!H", length)
@@ -4213,17 +4286,19 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = port_status()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_PORT_STATUS)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 64: raise loxi.ProtocolError("port_status length is %d, should be 64" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        obj.reason = struct.unpack_from('!B', buf, 8)[0]
-        obj.pad = list(struct.unpack_from('!7B', buf, 9))
-        obj.desc = common.port_desc.unpack(buffer(buf, 16))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_PORT_STATUS)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.reason = reader.read('!B')[0]
+        reader.skip(7)
+        obj.desc = common.port_desc.unpack(reader)
         return obj
 
     def __eq__(self, other):
@@ -4232,7 +4307,6 @@
         if self.type != other.type: return False
         if self.xid != other.xid: return False
         if self.reason != other.reason: return False
-        if self.pad != other.pad: return False
         if self.desc != other.desc: return False
         return True
 
@@ -4260,9 +4334,6 @@
                 q.text("reason = ");
                 q.text("%#x" % self.reason)
                 q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
-                q.text(","); q.breakable()
                 q.text("desc = ");
                 q.pp(self.desc)
             q.breakable()
@@ -4272,16 +4343,12 @@
     version = const.OFP_VERSION
     type = const.OFPT_QUEUE_GET_CONFIG_REPLY
 
-    def __init__(self, xid=None, port=None, pad=None, queues=None):
+    def __init__(self, xid=None, port=None, queues=None):
         self.xid = xid
         if port != None:
             self.port = port
         else:
             self.port = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0,0,0,0,0]
         if queues != None:
             self.queues = queues
         else:
@@ -4294,7 +4361,7 @@
         packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
         packed.append(struct.pack("!L", self.xid))
         packed.append(struct.pack("!H", self.port))
-        packed.append(struct.pack("!6B", *self.pad))
+        packed.append('\x00' * 6)
         packed.append("".join([x.pack() for x in self.queues]))
         length = sum([len(x) for x in packed])
         packed[2] = struct.pack("!H", length)
@@ -4304,17 +4371,19 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = queue_get_config_reply()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_QUEUE_GET_CONFIG_REPLY)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length < 16: raise loxi.ProtocolError("queue_get_config_reply length is %d, should be at least 16" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        obj.port = struct.unpack_from('!H', buf, 8)[0]
-        obj.pad = list(struct.unpack_from('!6B', buf, 10))
-        obj.queues = common.unpack_list_packet_queue(buffer(buf, 16))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_QUEUE_GET_CONFIG_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.port = reader.read('!H')[0]
+        reader.skip(6)
+        obj.queues = common.unpack_list_packet_queue(reader)
         return obj
 
     def __eq__(self, other):
@@ -4323,7 +4392,6 @@
         if self.type != other.type: return False
         if self.xid != other.xid: return False
         if self.port != other.port: return False
-        if self.pad != other.pad: return False
         if self.queues != other.queues: return False
         return True
 
@@ -4351,9 +4419,6 @@
                 q.text("port = ");
                 q.text(util.pretty_port(self.port))
                 q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
-                q.text(","); q.breakable()
                 q.text("queues = ");
                 q.pp(self.queues)
             q.breakable()
@@ -4363,16 +4428,12 @@
     version = const.OFP_VERSION
     type = const.OFPT_QUEUE_GET_CONFIG_REQUEST
 
-    def __init__(self, xid=None, port=None, pad=None):
+    def __init__(self, xid=None, port=None):
         self.xid = xid
         if port != None:
             self.port = port
         else:
             self.port = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0]
 
     def pack(self):
         packed = []
@@ -4381,7 +4442,7 @@
         packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
         packed.append(struct.pack("!L", self.xid))
         packed.append(struct.pack("!H", self.port))
-        packed.append(struct.pack("!2B", *self.pad))
+        packed.append('\x00' * 2)
         length = sum([len(x) for x in packed])
         packed[2] = struct.pack("!H", length)
         return ''.join(packed)
@@ -4390,16 +4451,18 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = queue_get_config_request()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_QUEUE_GET_CONFIG_REQUEST)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 12: raise loxi.ProtocolError("queue_get_config_request length is %d, should be 12" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        obj.port = struct.unpack_from('!H', buf, 8)[0]
-        obj.pad = list(struct.unpack_from('!2B', buf, 10))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_QUEUE_GET_CONFIG_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.port = reader.read('!H')[0]
+        reader.skip(2)
         return obj
 
     def __eq__(self, other):
@@ -4408,7 +4471,6 @@
         if self.type != other.type: return False
         if self.xid != other.xid: return False
         if self.port != other.port: return False
-        if self.pad != other.pad: return False
         return True
 
     def __ne__(self, other):
@@ -4434,9 +4496,6 @@
                 q.text(","); q.breakable()
                 q.text("port = ");
                 q.text(util.pretty_port(self.port))
-                q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
             q.breakable()
         q.text('}')
 
@@ -4473,18 +4532,20 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = queue_stats_reply()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_STATS_REPLY)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length < 12: raise loxi.ProtocolError("queue_stats_reply length is %d, should be at least 12" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        stats_type = struct.unpack_from('!H', buf, 8)[0]
-        assert(stats_type == const.OFPST_QUEUE)
-        obj.flags = struct.unpack_from('!H', buf, 10)[0]
-        obj.entries = util.unpack_array(common.queue_stats_entry.unpack, 32, buffer(buf, 12))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_QUEUE)
+        obj.flags = reader.read('!H')[0]
+        obj.entries = loxi.generic_util.unpack_list(reader, common.queue_stats_entry.unpack)
         return obj
 
     def __eq__(self, other):
@@ -4530,7 +4591,7 @@
     type = const.OFPT_STATS_REQUEST
     stats_type = const.OFPST_QUEUE
 
-    def __init__(self, xid=None, flags=None, port_no=None, pad=None, queue_id=None):
+    def __init__(self, xid=None, flags=None, port_no=None, queue_id=None):
         self.xid = xid
         if flags != None:
             self.flags = flags
@@ -4540,10 +4601,6 @@
             self.port_no = port_no
         else:
             self.port_no = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0]
         if queue_id != None:
             self.queue_id = queue_id
         else:
@@ -4558,7 +4615,7 @@
         packed.append(struct.pack("!H", self.stats_type))
         packed.append(struct.pack("!H", self.flags))
         packed.append(struct.pack("!H", self.port_no))
-        packed.append(struct.pack("!2B", *self.pad))
+        packed.append('\x00' * 2)
         packed.append(struct.pack("!L", self.queue_id))
         length = sum([len(x) for x in packed])
         packed[2] = struct.pack("!H", length)
@@ -4568,20 +4625,22 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = queue_stats_request()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_STATS_REQUEST)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 20: raise loxi.ProtocolError("queue_stats_request length is %d, should be 20" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        stats_type = struct.unpack_from('!H', buf, 8)[0]
-        assert(stats_type == const.OFPST_QUEUE)
-        obj.flags = struct.unpack_from('!H', buf, 10)[0]
-        obj.port_no = struct.unpack_from('!H', buf, 12)[0]
-        obj.pad = list(struct.unpack_from('!2B', buf, 14))
-        obj.queue_id = struct.unpack_from('!L', buf, 16)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_QUEUE)
+        obj.flags = reader.read('!H')[0]
+        obj.port_no = reader.read('!H')[0]
+        reader.skip(2)
+        obj.queue_id = reader.read('!L')[0]
         return obj
 
     def __eq__(self, other):
@@ -4591,7 +4650,6 @@
         if self.xid != other.xid: return False
         if self.flags != other.flags: return False
         if self.port_no != other.port_no: return False
-        if self.pad != other.pad: return False
         if self.queue_id != other.queue_id: return False
         return True
 
@@ -4622,9 +4680,6 @@
                 q.text("port_no = ");
                 q.text(util.pretty_port(self.port_no))
                 q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
-                q.text(","); q.breakable()
                 q.text("queue_id = ");
                 q.text("%#x" % self.queue_id)
             q.breakable()
@@ -4661,16 +4716,18 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = set_config()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_SET_CONFIG)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 12: raise loxi.ProtocolError("set_config length is %d, should be 12" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        obj.flags = struct.unpack_from('!H', buf, 8)[0]
-        obj.miss_send_len = struct.unpack_from('!H', buf, 10)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_SET_CONFIG)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.flags = reader.read('!H')[0]
+        obj.miss_send_len = reader.read('!H')[0]
         return obj
 
     def __eq__(self, other):
@@ -4715,16 +4772,12 @@
     version = const.OFP_VERSION
     type = 22
 
-    def __init__(self, xid=None, table_id=None, pad=None, config=None):
+    def __init__(self, xid=None, table_id=None, config=None):
         self.xid = xid
         if table_id != None:
             self.table_id = table_id
         else:
             self.table_id = 0
-        if pad != None:
-            self.pad = pad
-        else:
-            self.pad = [0,0,0]
         if config != None:
             self.config = config
         else:
@@ -4737,7 +4790,7 @@
         packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
         packed.append(struct.pack("!L", self.xid))
         packed.append(struct.pack("!B", self.table_id))
-        packed.append(struct.pack("!3B", *self.pad))
+        packed.append('\x00' * 3)
         packed.append(struct.pack("!L", self.config))
         length = sum([len(x) for x in packed])
         packed[2] = struct.pack("!H", length)
@@ -4747,17 +4800,19 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = table_mod()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == 22)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 16: raise loxi.ProtocolError("table_mod length is %d, should be 16" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        obj.table_id = struct.unpack_from('!B', buf, 8)[0]
-        obj.pad = list(struct.unpack_from('!3B', buf, 9))
-        obj.config = struct.unpack_from('!L', buf, 12)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == 22)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.table_id = reader.read('!B')[0]
+        reader.skip(3)
+        obj.config = reader.read('!L')[0]
         return obj
 
     def __eq__(self, other):
@@ -4766,7 +4821,6 @@
         if self.type != other.type: return False
         if self.xid != other.xid: return False
         if self.table_id != other.table_id: return False
-        if self.pad != other.pad: return False
         if self.config != other.config: return False
         return True
 
@@ -4794,9 +4848,6 @@
                 q.text("table_id = ");
                 q.text("%#x" % self.table_id)
                 q.text(","); q.breakable()
-                q.text("pad = ");
-                q.pp(self.pad)
-                q.text(","); q.breakable()
                 q.text("config = ");
                 q.text("%#x" % self.config)
             q.breakable()
@@ -4835,18 +4886,20 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = table_stats_reply()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_STATS_REPLY)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length < 12: raise loxi.ProtocolError("table_stats_reply length is %d, should be at least 12" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        stats_type = struct.unpack_from('!H', buf, 8)[0]
-        assert(stats_type == const.OFPST_TABLE)
-        obj.flags = struct.unpack_from('!H', buf, 10)[0]
-        obj.entries = util.unpack_array(common.table_stats_entry.unpack, 64, buffer(buf, 12))
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_TABLE)
+        obj.flags = reader.read('!H')[0]
+        obj.entries = loxi.generic_util.unpack_list(reader, common.table_stats_entry.unpack)
         return obj
 
     def __eq__(self, other):
@@ -4915,17 +4968,19 @@
     def unpack(buf):
         if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
         obj = table_stats_request()
-        version = struct.unpack_from('!B', buf, 0)[0]
-        assert(version == const.OFP_VERSION)
-        type = struct.unpack_from('!B', buf, 1)[0]
-        assert(type == const.OFPT_STATS_REQUEST)
-        _length = struct.unpack_from('!H', buf, 2)[0]
-        assert(_length == len(buf))
-        if _length != 12: raise loxi.ProtocolError("table_stats_request length is %d, should be 12" % _length)
-        obj.xid = struct.unpack_from('!L', buf, 4)[0]
-        stats_type = struct.unpack_from('!H', buf, 8)[0]
-        assert(stats_type == const.OFPST_TABLE)
-        obj.flags = struct.unpack_from('!H', buf, 10)[0]
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_TABLE)
+        obj.flags = reader.read('!H')[0]
         return obj
 
     def __eq__(self, other):
@@ -5091,6 +5146,7 @@
         4: bsn_get_mirroring_request.unpack,
         0: bsn_set_ip_mask.unpack,
         3: bsn_set_mirroring.unpack,
+        11: bsn_set_pktin_suppression.unpack,
         6: bsn_shell_command.unpack,
         7: bsn_shell_output.unpack,
         8: bsn_shell_status.unpack,
diff --git a/src/python/loxi/of10/util.py b/src/python/loxi/of10/util.py
index 713d5cb..45aa2d0 100644
--- a/src/python/loxi/of10/util.py
+++ b/src/python/loxi/of10/util.py
@@ -1,32 +1,13 @@
-#
-# Copyright 2012, 2013, Big Switch Networks, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
 
 # Automatically generated by LOXI from template util.py
 # Do not modify
 
 import loxi
 import const
-
-def unpack_array(deserializer, element_size, buf):
-    """
-    Deserialize an array of fixed length elements.
-    The deserializer function should take a buffer and return the new object.
-    """
-    if len(buf) % element_size != 0: raise loxi.ProtocolError("invalid array length")
-    n = len(buf) / element_size
-    return [deserializer(buffer(buf, i*element_size, element_size)) for i in range(n)]
+import struct
 
 def pretty_mac(mac):
     return ':'.join(["%02x" % x for x in mac])
diff --git a/src/python/loxi/of11/__init__.py b/src/python/loxi/of11/__init__.py
new file mode 100644
index 0000000..edb9e20
--- /dev/null
+++ b/src/python/loxi/of11/__init__.py
@@ -0,0 +1,12 @@
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+
+# Automatically generated by LOXI from template init.py
+# Do not modify
+
+import action, common, const, message
+import instruction
+from const import *
+from common import *
+from loxi import ProtocolError
diff --git a/src/python/loxi/of11/action.py b/src/python/loxi/of11/action.py
new file mode 100644
index 0000000..7853607
--- /dev/null
+++ b/src/python/loxi/of11/action.py
@@ -0,0 +1,1629 @@
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+
+# Automatically generated by LOXI from template action.py
+# Do not modify
+
+import struct
+import const
+import util
+import loxi.generic_util
+import loxi
+
+def unpack_list(reader):
+    def deserializer(reader, typ):
+        parser = parsers.get(typ)
+        if not parser: raise loxi.ProtocolError("unknown action type %d" % typ)
+        return parser(reader)
+    return loxi.generic_util.unpack_list_tlv16(reader, deserializer)
+
+class Action(object):
+    type = None # override in subclass
+    pass
+
+class bsn_mirror(Action):
+    type = const.OFPAT_EXPERIMENTER
+    experimenter = 0x5c16c7
+    subtype = 1
+
+    def __init__(self, dest_port=None, vlan_tag=None, copy_stage=None):
+        if dest_port != None:
+            self.dest_port = dest_port
+        else:
+            self.dest_port = 0
+        if vlan_tag != None:
+            self.vlan_tag = vlan_tag
+        else:
+            self.vlan_tag = 0
+        if copy_stage != None:
+            self.copy_stage = copy_stage
+        else:
+            self.copy_stage = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        packed.append(struct.pack("!L", self.dest_port))
+        packed.append(struct.pack("!L", self.vlan_tag))
+        packed.append(struct.pack("!B", self.copy_stage))
+        packed.append('\x00' * 3)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = bsn_mirror()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_EXPERIMENTER)
+        _len = reader.read('!H')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 1)
+        obj.dest_port = reader.read('!L')[0]
+        obj.vlan_tag = reader.read('!L')[0]
+        obj.copy_stage = reader.read('!B')[0]
+        reader.skip(3)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.dest_port != other.dest_port: return False
+        if self.vlan_tag != other.vlan_tag: return False
+        if self.copy_stage != other.copy_stage: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_mirror {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("dest_port = ");
+                q.text("%#x" % self.dest_port)
+                q.text(","); q.breakable()
+                q.text("vlan_tag = ");
+                q.text("%#x" % self.vlan_tag)
+                q.text(","); q.breakable()
+                q.text("copy_stage = ");
+                q.text("%#x" % self.copy_stage)
+            q.breakable()
+        q.text('}')
+
+class bsn_set_tunnel_dst(Action):
+    type = const.OFPAT_EXPERIMENTER
+    experimenter = 0x5c16c7
+    subtype = 2
+
+    def __init__(self, dst=None):
+        if dst != None:
+            self.dst = dst
+        else:
+            self.dst = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        packed.append(struct.pack("!L", self.dst))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = bsn_set_tunnel_dst()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_EXPERIMENTER)
+        _len = reader.read('!H')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 2)
+        obj.dst = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.dst != other.dst: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_set_tunnel_dst {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("dst = ");
+                q.text("%#x" % self.dst)
+            q.breakable()
+        q.text('}')
+
+class copy_ttl_in(Action):
+    type = const.OFPAT_COPY_TTL_IN
+
+    def __init__(self):
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = copy_ttl_in()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_COPY_TTL_IN)
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("copy_ttl_in {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+            q.breakable()
+        q.text('}')
+
+class copy_ttl_out(Action):
+    type = const.OFPAT_COPY_TTL_OUT
+
+    def __init__(self):
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = copy_ttl_out()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_COPY_TTL_OUT)
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("copy_ttl_out {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+            q.breakable()
+        q.text('}')
+
+class dec_mpls_ttl(Action):
+    type = const.OFPAT_DEC_MPLS_TTL
+
+    def __init__(self):
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = dec_mpls_ttl()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_DEC_MPLS_TTL)
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("dec_mpls_ttl {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+            q.breakable()
+        q.text('}')
+
+class dec_nw_ttl(Action):
+    type = const.OFPAT_DEC_NW_TTL
+
+    def __init__(self):
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = dec_nw_ttl()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_DEC_NW_TTL)
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("dec_nw_ttl {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+            q.breakable()
+        q.text('}')
+
+class group(Action):
+    type = const.OFPAT_GROUP
+
+    def __init__(self, group_id=None):
+        if group_id != None:
+            self.group_id = group_id
+        else:
+            self.group_id = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!L", self.group_id))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = group()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_GROUP)
+        _len = reader.read('!H')[0]
+        obj.group_id = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.group_id != other.group_id: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("group_id = ");
+                q.text("%#x" % self.group_id)
+            q.breakable()
+        q.text('}')
+
+class nicira_dec_ttl(Action):
+    type = const.OFPAT_EXPERIMENTER
+    experimenter = 0x2320
+    subtype = 18
+
+    def __init__(self):
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!H", self.subtype))
+        packed.append('\x00' * 2)
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = nicira_dec_ttl()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_EXPERIMENTER)
+        _len = reader.read('!H')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x2320)
+        _subtype = reader.read('!H')[0]
+        assert(_subtype == 18)
+        reader.skip(2)
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("nicira_dec_ttl {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+            q.breakable()
+        q.text('}')
+
+class output(Action):
+    type = const.OFPAT_OUTPUT
+
+    def __init__(self, port=None, max_len=None):
+        if port != None:
+            self.port = port
+        else:
+            self.port = 0
+        if max_len != None:
+            self.max_len = max_len
+        else:
+            self.max_len = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!L", self.port))
+        packed.append(struct.pack("!H", self.max_len))
+        packed.append('\x00' * 6)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = output()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_OUTPUT)
+        _len = reader.read('!H')[0]
+        obj.port = reader.read('!L')[0]
+        obj.max_len = reader.read('!H')[0]
+        reader.skip(6)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.port != other.port: return False
+        if self.max_len != other.max_len: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("output {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("port = ");
+                q.text(util.pretty_port(self.port))
+                q.text(","); q.breakable()
+                q.text("max_len = ");
+                q.text("%#x" % self.max_len)
+            q.breakable()
+        q.text('}')
+
+class pop_mpls(Action):
+    type = const.OFPAT_POP_MPLS
+
+    def __init__(self, ethertype=None):
+        if ethertype != None:
+            self.ethertype = ethertype
+        else:
+            self.ethertype = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!H", self.ethertype))
+        packed.append('\x00' * 2)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = pop_mpls()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_POP_MPLS)
+        _len = reader.read('!H')[0]
+        obj.ethertype = reader.read('!H')[0]
+        reader.skip(2)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.ethertype != other.ethertype: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("pop_mpls {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("ethertype = ");
+                q.text("%#x" % self.ethertype)
+            q.breakable()
+        q.text('}')
+
+class pop_vlan(Action):
+    type = const.OFPAT_POP_VLAN
+
+    def __init__(self):
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = pop_vlan()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_POP_VLAN)
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("pop_vlan {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+            q.breakable()
+        q.text('}')
+
+class push_mpls(Action):
+    type = const.OFPAT_PUSH_MPLS
+
+    def __init__(self, ethertype=None):
+        if ethertype != None:
+            self.ethertype = ethertype
+        else:
+            self.ethertype = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!H", self.ethertype))
+        packed.append('\x00' * 2)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = push_mpls()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_PUSH_MPLS)
+        _len = reader.read('!H')[0]
+        obj.ethertype = reader.read('!H')[0]
+        reader.skip(2)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.ethertype != other.ethertype: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("push_mpls {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("ethertype = ");
+                q.text("%#x" % self.ethertype)
+            q.breakable()
+        q.text('}')
+
+class push_vlan(Action):
+    type = const.OFPAT_PUSH_VLAN
+
+    def __init__(self, ethertype=None):
+        if ethertype != None:
+            self.ethertype = ethertype
+        else:
+            self.ethertype = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!H", self.ethertype))
+        packed.append('\x00' * 2)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = push_vlan()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_PUSH_VLAN)
+        _len = reader.read('!H')[0]
+        obj.ethertype = reader.read('!H')[0]
+        reader.skip(2)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.ethertype != other.ethertype: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("push_vlan {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("ethertype = ");
+                q.text("%#x" % self.ethertype)
+            q.breakable()
+        q.text('}')
+
+class set_dl_dst(Action):
+    type = const.OFPAT_SET_DL_DST
+
+    def __init__(self, dl_addr=None):
+        if dl_addr != None:
+            self.dl_addr = dl_addr
+        else:
+            self.dl_addr = [0,0,0,0,0,0]
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!6B", *self.dl_addr))
+        packed.append('\x00' * 6)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = set_dl_dst()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_DL_DST)
+        _len = reader.read('!H')[0]
+        obj.dl_addr = list(reader.read('!6B'))
+        reader.skip(6)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.dl_addr != other.dl_addr: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("set_dl_dst {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("dl_addr = ");
+                q.text(util.pretty_mac(self.dl_addr))
+            q.breakable()
+        q.text('}')
+
+class set_dl_src(Action):
+    type = const.OFPAT_SET_DL_SRC
+
+    def __init__(self, dl_addr=None):
+        if dl_addr != None:
+            self.dl_addr = dl_addr
+        else:
+            self.dl_addr = [0,0,0,0,0,0]
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!6B", *self.dl_addr))
+        packed.append('\x00' * 6)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = set_dl_src()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_DL_SRC)
+        _len = reader.read('!H')[0]
+        obj.dl_addr = list(reader.read('!6B'))
+        reader.skip(6)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.dl_addr != other.dl_addr: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("set_dl_src {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("dl_addr = ");
+                q.text(util.pretty_mac(self.dl_addr))
+            q.breakable()
+        q.text('}')
+
+class set_mpls_label(Action):
+    type = const.OFPAT_SET_MPLS_LABEL
+
+    def __init__(self, mpls_label=None):
+        if mpls_label != None:
+            self.mpls_label = mpls_label
+        else:
+            self.mpls_label = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!L", self.mpls_label))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = set_mpls_label()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_MPLS_LABEL)
+        _len = reader.read('!H')[0]
+        obj.mpls_label = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.mpls_label != other.mpls_label: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("set_mpls_label {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("mpls_label = ");
+                q.text("%#x" % self.mpls_label)
+            q.breakable()
+        q.text('}')
+
+class set_mpls_tc(Action):
+    type = const.OFPAT_SET_MPLS_TC
+
+    def __init__(self, mpls_tc=None):
+        if mpls_tc != None:
+            self.mpls_tc = mpls_tc
+        else:
+            self.mpls_tc = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!B", self.mpls_tc))
+        packed.append('\x00' * 3)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = set_mpls_tc()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_MPLS_TC)
+        _len = reader.read('!H')[0]
+        obj.mpls_tc = reader.read('!B')[0]
+        reader.skip(3)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.mpls_tc != other.mpls_tc: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("set_mpls_tc {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("mpls_tc = ");
+                q.text("%#x" % self.mpls_tc)
+            q.breakable()
+        q.text('}')
+
+class set_mpls_ttl(Action):
+    type = const.OFPAT_SET_MPLS_TTL
+
+    def __init__(self, mpls_ttl=None):
+        if mpls_ttl != None:
+            self.mpls_ttl = mpls_ttl
+        else:
+            self.mpls_ttl = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!B", self.mpls_ttl))
+        packed.append('\x00' * 3)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = set_mpls_ttl()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_MPLS_TTL)
+        _len = reader.read('!H')[0]
+        obj.mpls_ttl = reader.read('!B')[0]
+        reader.skip(3)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.mpls_ttl != other.mpls_ttl: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("set_mpls_ttl {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("mpls_ttl = ");
+                q.text("%#x" % self.mpls_ttl)
+            q.breakable()
+        q.text('}')
+
+class set_nw_dst(Action):
+    type = const.OFPAT_SET_NW_DST
+
+    def __init__(self, nw_addr=None):
+        if nw_addr != None:
+            self.nw_addr = nw_addr
+        else:
+            self.nw_addr = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!L", self.nw_addr))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = set_nw_dst()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_NW_DST)
+        _len = reader.read('!H')[0]
+        obj.nw_addr = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.nw_addr != other.nw_addr: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("set_nw_dst {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("nw_addr = ");
+                q.text("%#x" % self.nw_addr)
+            q.breakable()
+        q.text('}')
+
+class set_nw_ecn(Action):
+    type = const.OFPAT_SET_NW_ECN
+
+    def __init__(self, nw_ecn=None):
+        if nw_ecn != None:
+            self.nw_ecn = nw_ecn
+        else:
+            self.nw_ecn = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!B", self.nw_ecn))
+        packed.append('\x00' * 3)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = set_nw_ecn()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_NW_ECN)
+        _len = reader.read('!H')[0]
+        obj.nw_ecn = reader.read('!B')[0]
+        reader.skip(3)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.nw_ecn != other.nw_ecn: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("set_nw_ecn {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("nw_ecn = ");
+                q.text("%#x" % self.nw_ecn)
+            q.breakable()
+        q.text('}')
+
+class set_nw_src(Action):
+    type = const.OFPAT_SET_NW_SRC
+
+    def __init__(self, nw_addr=None):
+        if nw_addr != None:
+            self.nw_addr = nw_addr
+        else:
+            self.nw_addr = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!L", self.nw_addr))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = set_nw_src()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_NW_SRC)
+        _len = reader.read('!H')[0]
+        obj.nw_addr = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.nw_addr != other.nw_addr: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("set_nw_src {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("nw_addr = ");
+                q.text("%#x" % self.nw_addr)
+            q.breakable()
+        q.text('}')
+
+class set_nw_tos(Action):
+    type = const.OFPAT_SET_NW_TOS
+
+    def __init__(self, nw_tos=None):
+        if nw_tos != None:
+            self.nw_tos = nw_tos
+        else:
+            self.nw_tos = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!B", self.nw_tos))
+        packed.append('\x00' * 3)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = set_nw_tos()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_NW_TOS)
+        _len = reader.read('!H')[0]
+        obj.nw_tos = reader.read('!B')[0]
+        reader.skip(3)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.nw_tos != other.nw_tos: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("set_nw_tos {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("nw_tos = ");
+                q.text("%#x" % self.nw_tos)
+            q.breakable()
+        q.text('}')
+
+class set_nw_ttl(Action):
+    type = const.OFPAT_SET_NW_TTL
+
+    def __init__(self, nw_ttl=None):
+        if nw_ttl != None:
+            self.nw_ttl = nw_ttl
+        else:
+            self.nw_ttl = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!B", self.nw_ttl))
+        packed.append('\x00' * 3)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = set_nw_ttl()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_NW_TTL)
+        _len = reader.read('!H')[0]
+        obj.nw_ttl = reader.read('!B')[0]
+        reader.skip(3)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.nw_ttl != other.nw_ttl: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("set_nw_ttl {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("nw_ttl = ");
+                q.text("%#x" % self.nw_ttl)
+            q.breakable()
+        q.text('}')
+
+class set_queue(Action):
+    type = const.OFPAT_SET_QUEUE
+
+    def __init__(self, queue_id=None):
+        if queue_id != None:
+            self.queue_id = queue_id
+        else:
+            self.queue_id = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!L", self.queue_id))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = set_queue()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_QUEUE)
+        _len = reader.read('!H')[0]
+        obj.queue_id = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.queue_id != other.queue_id: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("set_queue {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("queue_id = ");
+                q.text("%#x" % self.queue_id)
+            q.breakable()
+        q.text('}')
+
+class set_tp_dst(Action):
+    type = const.OFPAT_SET_TP_DST
+
+    def __init__(self, tp_port=None):
+        if tp_port != None:
+            self.tp_port = tp_port
+        else:
+            self.tp_port = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!H", self.tp_port))
+        packed.append('\x00' * 2)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = set_tp_dst()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_TP_DST)
+        _len = reader.read('!H')[0]
+        obj.tp_port = reader.read('!H')[0]
+        reader.skip(2)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.tp_port != other.tp_port: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("set_tp_dst {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("tp_port = ");
+                q.text("%#x" % self.tp_port)
+            q.breakable()
+        q.text('}')
+
+class set_tp_src(Action):
+    type = const.OFPAT_SET_TP_SRC
+
+    def __init__(self, tp_port=None):
+        if tp_port != None:
+            self.tp_port = tp_port
+        else:
+            self.tp_port = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!H", self.tp_port))
+        packed.append('\x00' * 2)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = set_tp_src()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_TP_SRC)
+        _len = reader.read('!H')[0]
+        obj.tp_port = reader.read('!H')[0]
+        reader.skip(2)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.tp_port != other.tp_port: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("set_tp_src {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("tp_port = ");
+                q.text("%#x" % self.tp_port)
+            q.breakable()
+        q.text('}')
+
+class set_vlan_pcp(Action):
+    type = const.OFPAT_SET_VLAN_PCP
+
+    def __init__(self, vlan_pcp=None):
+        if vlan_pcp != None:
+            self.vlan_pcp = vlan_pcp
+        else:
+            self.vlan_pcp = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!B", self.vlan_pcp))
+        packed.append('\x00' * 3)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = set_vlan_pcp()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_VLAN_PCP)
+        _len = reader.read('!H')[0]
+        obj.vlan_pcp = reader.read('!B')[0]
+        reader.skip(3)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.vlan_pcp != other.vlan_pcp: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("set_vlan_pcp {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("vlan_pcp = ");
+                q.text("%#x" % self.vlan_pcp)
+            q.breakable()
+        q.text('}')
+
+class set_vlan_vid(Action):
+    type = const.OFPAT_SET_VLAN_VID
+
+    def __init__(self, vlan_vid=None):
+        if vlan_vid != None:
+            self.vlan_vid = vlan_vid
+        else:
+            self.vlan_vid = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!H", self.vlan_vid))
+        packed.append('\x00' * 2)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = set_vlan_vid()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_VLAN_VID)
+        _len = reader.read('!H')[0]
+        obj.vlan_vid = reader.read('!H')[0]
+        reader.skip(2)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.vlan_vid != other.vlan_vid: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("set_vlan_vid {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("vlan_vid = ");
+                q.text("%#x" % self.vlan_vid)
+            q.breakable()
+        q.text('}')
+
+
+def parse_experimenter(reader):
+
+    experimenter, = reader.peek("!4xL")
+    if experimenter == 0x005c16c7: # Big Switch Networks
+        subtype, = reader.peek("!8xL")
+    elif experimenter == 0x00002320: # Nicira
+        subtype, = reader.peek("!8xH")
+    else:
+        raise loxi.ProtocolError("unexpected experimenter id %#x" % experimenter)
+
+    if subtype in experimenter_parsers[experimenter]:
+        return experimenter_parsers[experimenter][subtype](reader)
+    else:
+        raise loxi.ProtocolError("unexpected BSN experimenter subtype %#x" % subtype)
+
+parsers = {
+    const.OFPAT_COPY_TTL_IN : copy_ttl_in.unpack,
+    const.OFPAT_COPY_TTL_OUT : copy_ttl_out.unpack,
+    const.OFPAT_DEC_MPLS_TTL : dec_mpls_ttl.unpack,
+    const.OFPAT_DEC_NW_TTL : dec_nw_ttl.unpack,
+    const.OFPAT_EXPERIMENTER : parse_experimenter,
+    const.OFPAT_GROUP : group.unpack,
+    const.OFPAT_OUTPUT : output.unpack,
+    const.OFPAT_POP_MPLS : pop_mpls.unpack,
+    const.OFPAT_POP_VLAN : pop_vlan.unpack,
+    const.OFPAT_PUSH_MPLS : push_mpls.unpack,
+    const.OFPAT_PUSH_VLAN : push_vlan.unpack,
+    const.OFPAT_SET_DL_DST : set_dl_dst.unpack,
+    const.OFPAT_SET_DL_SRC : set_dl_src.unpack,
+    const.OFPAT_SET_MPLS_LABEL : set_mpls_label.unpack,
+    const.OFPAT_SET_MPLS_TC : set_mpls_tc.unpack,
+    const.OFPAT_SET_MPLS_TTL : set_mpls_ttl.unpack,
+    const.OFPAT_SET_NW_DST : set_nw_dst.unpack,
+    const.OFPAT_SET_NW_ECN : set_nw_ecn.unpack,
+    const.OFPAT_SET_NW_SRC : set_nw_src.unpack,
+    const.OFPAT_SET_NW_TOS : set_nw_tos.unpack,
+    const.OFPAT_SET_NW_TTL : set_nw_ttl.unpack,
+    const.OFPAT_SET_QUEUE : set_queue.unpack,
+    const.OFPAT_SET_TP_DST : set_tp_dst.unpack,
+    const.OFPAT_SET_TP_SRC : set_tp_src.unpack,
+    const.OFPAT_SET_VLAN_PCP : set_vlan_pcp.unpack,
+    const.OFPAT_SET_VLAN_VID : set_vlan_vid.unpack,
+}
+
+experimenter_parsers = {
+}
diff --git a/src/python/loxi/of11/common.py b/src/python/loxi/of11/common.py
new file mode 100644
index 0000000..138d451
--- /dev/null
+++ b/src/python/loxi/of11/common.py
@@ -0,0 +1,1537 @@
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+
+# Automatically generated by LOXI from template common.py
+# Do not modify
+
+import sys
+import struct
+import action
+import instruction # for unpack_list
+import const
+import util
+import loxi.generic_util
+
+
+# HACK make this module visible as 'common' to simplify code generation
+common = sys.modules[__name__]
+
+def unpack_list_flow_stats_entry(reader):
+    return loxi.generic_util.unpack_list_lv16(reader, flow_stats_entry.unpack)
+
+def unpack_list_queue_prop(reader):
+    def deserializer(reader, typ):
+        if typ == const.OFPQT_MIN_RATE:
+            return queue_prop_min_rate.unpack(reader)
+        else:
+            raise loxi.ProtocolError("unknown queue prop %d" % typ)
+    return loxi.generic_util.unpack_list_tlv16(reader, deserializer)
+
+def unpack_list_packet_queue(reader):
+    def wrapper(reader):
+        length, = reader.peek('!4xH')
+        return packet_queue.unpack(reader.slice(length))
+    return loxi.generic_util.unpack_list(reader, wrapper)
+
+def unpack_list_hello_elem(reader):
+    def deserializer(reader, typ):
+        if typ == const.OFPHET_VERSIONBITMAP:
+            return hello_elem_versionbitmap.unpack(reader)
+        else:
+            return None
+    return [x for x in loxi.generic_util.unpack_list_tlv16(reader, deserializer) if x != None]
+
+def unpack_list_bucket(reader):
+    return loxi.generic_util.unpack_list_lv16(reader, bucket.unpack)
+
+def unpack_list_group_desc_stats_entry(reader):
+    return loxi.generic_util.unpack_list_lv16(reader, group_desc_stats_entry.unpack)
+
+def unpack_list_group_stats_entry(reader):
+    return loxi.generic_util.unpack_list_lv16(reader, group_stats_entry.unpack)
+
+def unpack_list_meter_stats(reader):
+    def wrapper(reader):
+        length, = reader.peek('!4xH')
+        return meter_stats.unpack(reader.slice(length))
+    return loxi.generic_util.unpack_list(reader, wrapper)
+
+class bsn_interface(object):
+
+    def __init__(self, hw_addr=None, name=None, ipv4_addr=None, ipv4_netmask=None):
+        if hw_addr != None:
+            self.hw_addr = hw_addr
+        else:
+            self.hw_addr = [0,0,0,0,0,0]
+        if name != None:
+            self.name = name
+        else:
+            self.name = ""
+        if ipv4_addr != None:
+            self.ipv4_addr = ipv4_addr
+        else:
+            self.ipv4_addr = 0
+        if ipv4_netmask != None:
+            self.ipv4_netmask = ipv4_netmask
+        else:
+            self.ipv4_netmask = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!6B", *self.hw_addr))
+        packed.append('\x00' * 2)
+        packed.append(struct.pack("!16s", self.name))
+        packed.append(struct.pack("!L", self.ipv4_addr))
+        packed.append(struct.pack("!L", self.ipv4_netmask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = bsn_interface()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.hw_addr = list(reader.read('!6B'))
+        reader.skip(2)
+        obj.name = reader.read("!16s")[0].rstrip("\x00")
+        obj.ipv4_addr = reader.read('!L')[0]
+        obj.ipv4_netmask = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.hw_addr != other.hw_addr: return False
+        if self.name != other.name: return False
+        if self.ipv4_addr != other.ipv4_addr: return False
+        if self.ipv4_netmask != other.ipv4_netmask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_interface {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("hw_addr = ");
+                q.text(util.pretty_mac(self.hw_addr))
+                q.text(","); q.breakable()
+                q.text("name = ");
+                q.pp(self.name)
+                q.text(","); q.breakable()
+                q.text("ipv4_addr = ");
+                q.text(util.pretty_ipv4(self.ipv4_addr))
+                q.text(","); q.breakable()
+                q.text("ipv4_netmask = ");
+                q.text(util.pretty_ipv4(self.ipv4_netmask))
+            q.breakable()
+        q.text('}')
+
+class bucket(object):
+
+    def __init__(self, weight=None, watch_port=None, watch_group=None, actions=None):
+        if weight != None:
+            self.weight = weight
+        else:
+            self.weight = 0
+        if watch_port != None:
+            self.watch_port = watch_port
+        else:
+            self.watch_port = 0
+        if watch_group != None:
+            self.watch_group = watch_group
+        else:
+            self.watch_group = 0
+        if actions != None:
+            self.actions = actions
+        else:
+            self.actions = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 0
+        packed.append(struct.pack("!H", self.weight))
+        packed.append(struct.pack("!L", self.watch_port))
+        packed.append(struct.pack("!L", self.watch_group))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.actions]))
+        length = sum([len(x) for x in packed])
+        packed[0] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = bucket()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _len = reader.read('!H')[0]
+        obj.weight = reader.read('!H')[0]
+        obj.watch_port = reader.read('!L')[0]
+        obj.watch_group = reader.read('!L')[0]
+        reader.skip(4)
+        obj.actions = action.unpack_list(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.weight != other.weight: return False
+        if self.watch_port != other.watch_port: return False
+        if self.watch_group != other.watch_group: return False
+        if self.actions != other.actions: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bucket {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("weight = ");
+                q.text("%#x" % self.weight)
+                q.text(","); q.breakable()
+                q.text("watch_port = ");
+                q.text(util.pretty_port(self.watch_port))
+                q.text(","); q.breakable()
+                q.text("watch_group = ");
+                q.text("%#x" % self.watch_group)
+                q.text(","); q.breakable()
+                q.text("actions = ");
+                q.pp(self.actions)
+            q.breakable()
+        q.text('}')
+
+class bucket_counter(object):
+
+    def __init__(self, packet_count=None, byte_count=None):
+        if packet_count != None:
+            self.packet_count = packet_count
+        else:
+            self.packet_count = 0
+        if byte_count != None:
+            self.byte_count = byte_count
+        else:
+            self.byte_count = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!Q", self.packet_count))
+        packed.append(struct.pack("!Q", self.byte_count))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = bucket_counter()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.packet_count = reader.read('!Q')[0]
+        obj.byte_count = reader.read('!Q')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.packet_count != other.packet_count: return False
+        if self.byte_count != other.byte_count: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bucket_counter {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("packet_count = ");
+                q.text("%#x" % self.packet_count)
+                q.text(","); q.breakable()
+                q.text("byte_count = ");
+                q.text("%#x" % self.byte_count)
+            q.breakable()
+        q.text('}')
+
+class flow_stats_entry(object):
+
+    def __init__(self, table_id=None, duration_sec=None, duration_nsec=None, priority=None, idle_timeout=None, hard_timeout=None, cookie=None, packet_count=None, byte_count=None, match=None, instructions=None):
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if duration_sec != None:
+            self.duration_sec = duration_sec
+        else:
+            self.duration_sec = 0
+        if duration_nsec != None:
+            self.duration_nsec = duration_nsec
+        else:
+            self.duration_nsec = 0
+        if priority != None:
+            self.priority = priority
+        else:
+            self.priority = 0
+        if idle_timeout != None:
+            self.idle_timeout = idle_timeout
+        else:
+            self.idle_timeout = 0
+        if hard_timeout != None:
+            self.hard_timeout = hard_timeout
+        else:
+            self.hard_timeout = 0
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if packet_count != None:
+            self.packet_count = packet_count
+        else:
+            self.packet_count = 0
+        if byte_count != None:
+            self.byte_count = byte_count
+        else:
+            self.byte_count = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+        if instructions != None:
+            self.instructions = instructions
+        else:
+            self.instructions = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 0
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append('\x00' * 1)
+        packed.append(struct.pack("!L", self.duration_sec))
+        packed.append(struct.pack("!L", self.duration_nsec))
+        packed.append(struct.pack("!H", self.priority))
+        packed.append(struct.pack("!H", self.idle_timeout))
+        packed.append(struct.pack("!H", self.hard_timeout))
+        packed.append('\x00' * 6)
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!Q", self.packet_count))
+        packed.append(struct.pack("!Q", self.byte_count))
+        packed.append(self.match.pack())
+        packed.append("".join([x.pack() for x in self.instructions]))
+        length = sum([len(x) for x in packed])
+        packed[0] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = flow_stats_entry()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _length = reader.read('!H')[0]
+        obj.table_id = reader.read('!B')[0]
+        reader.skip(1)
+        obj.duration_sec = reader.read('!L')[0]
+        obj.duration_nsec = reader.read('!L')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        reader.skip(6)
+        obj.cookie = reader.read('!Q')[0]
+        obj.packet_count = reader.read('!Q')[0]
+        obj.byte_count = reader.read('!Q')[0]
+        obj.match = common.match.unpack(reader)
+        obj.instructions = instruction.unpack_list(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.table_id != other.table_id: return False
+        if self.duration_sec != other.duration_sec: return False
+        if self.duration_nsec != other.duration_nsec: return False
+        if self.priority != other.priority: return False
+        if self.idle_timeout != other.idle_timeout: return False
+        if self.hard_timeout != other.hard_timeout: return False
+        if self.cookie != other.cookie: return False
+        if self.packet_count != other.packet_count: return False
+        if self.byte_count != other.byte_count: return False
+        if self.match != other.match: return False
+        if self.instructions != other.instructions: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_stats_entry {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("duration_sec = ");
+                q.text("%#x" % self.duration_sec)
+                q.text(","); q.breakable()
+                q.text("duration_nsec = ");
+                q.text("%#x" % self.duration_nsec)
+                q.text(","); q.breakable()
+                q.text("priority = ");
+                q.text("%#x" % self.priority)
+                q.text(","); q.breakable()
+                q.text("idle_timeout = ");
+                q.text("%#x" % self.idle_timeout)
+                q.text(","); q.breakable()
+                q.text("hard_timeout = ");
+                q.text("%#x" % self.hard_timeout)
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("packet_count = ");
+                q.text("%#x" % self.packet_count)
+                q.text(","); q.breakable()
+                q.text("byte_count = ");
+                q.text("%#x" % self.byte_count)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+                q.text(","); q.breakable()
+                q.text("instructions = ");
+                q.pp(self.instructions)
+            q.breakable()
+        q.text('}')
+
+class group_desc_stats_entry(object):
+
+    def __init__(self, type=None, group_id=None, buckets=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        if group_id != None:
+            self.group_id = group_id
+        else:
+            self.group_id = 0
+        if buckets != None:
+            self.buckets = buckets
+        else:
+            self.buckets = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 0
+        packed.append(struct.pack("!B", self.type))
+        packed.append('\x00' * 1)
+        packed.append(struct.pack("!L", self.group_id))
+        packed.append("".join([x.pack() for x in self.buckets]))
+        length = sum([len(x) for x in packed])
+        packed[0] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = group_desc_stats_entry()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _length = reader.read('!H')[0]
+        obj.type = reader.read('!B')[0]
+        reader.skip(1)
+        obj.group_id = reader.read('!L')[0]
+        obj.buckets = common.unpack_list_bucket(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        if self.group_id != other.group_id: return False
+        if self.buckets != other.buckets: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group_desc_stats_entry {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+                q.text(","); q.breakable()
+                q.text("group_id = ");
+                q.text("%#x" % self.group_id)
+                q.text(","); q.breakable()
+                q.text("buckets = ");
+                q.pp(self.buckets)
+            q.breakable()
+        q.text('}')
+
+class group_stats_entry(object):
+
+    def __init__(self, group_id=None, ref_count=None, packet_count=None, byte_count=None, bucket_stats=None):
+        if group_id != None:
+            self.group_id = group_id
+        else:
+            self.group_id = 0
+        if ref_count != None:
+            self.ref_count = ref_count
+        else:
+            self.ref_count = 0
+        if packet_count != None:
+            self.packet_count = packet_count
+        else:
+            self.packet_count = 0
+        if byte_count != None:
+            self.byte_count = byte_count
+        else:
+            self.byte_count = 0
+        if bucket_stats != None:
+            self.bucket_stats = bucket_stats
+        else:
+            self.bucket_stats = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 0
+        packed.append('\x00' * 2)
+        packed.append(struct.pack("!L", self.group_id))
+        packed.append(struct.pack("!L", self.ref_count))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!Q", self.packet_count))
+        packed.append(struct.pack("!Q", self.byte_count))
+        packed.append("".join([x.pack() for x in self.bucket_stats]))
+        length = sum([len(x) for x in packed])
+        packed[0] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = group_stats_entry()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _length = reader.read('!H')[0]
+        reader.skip(2)
+        obj.group_id = reader.read('!L')[0]
+        obj.ref_count = reader.read('!L')[0]
+        reader.skip(4)
+        obj.packet_count = reader.read('!Q')[0]
+        obj.byte_count = reader.read('!Q')[0]
+        obj.bucket_stats = loxi.generic_util.unpack_list(reader, common.bucket_counter.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.group_id != other.group_id: return False
+        if self.ref_count != other.ref_count: return False
+        if self.packet_count != other.packet_count: return False
+        if self.byte_count != other.byte_count: return False
+        if self.bucket_stats != other.bucket_stats: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group_stats_entry {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("group_id = ");
+                q.text("%#x" % self.group_id)
+                q.text(","); q.breakable()
+                q.text("ref_count = ");
+                q.text("%#x" % self.ref_count)
+                q.text(","); q.breakable()
+                q.text("packet_count = ");
+                q.text("%#x" % self.packet_count)
+                q.text(","); q.breakable()
+                q.text("byte_count = ");
+                q.text("%#x" % self.byte_count)
+                q.text(","); q.breakable()
+                q.text("bucket_stats = ");
+                q.pp(self.bucket_stats)
+            q.breakable()
+        q.text('}')
+
+class match_v2(object):
+    type = 0
+
+    def __init__(self, in_port=None, wildcards=None, eth_src=None, eth_src_mask=None, eth_dst=None, eth_dst_mask=None, vlan_vid=None, vlan_pcp=None, eth_type=None, ip_dscp=None, ip_proto=None, ipv4_src=None, ipv4_src_mask=None, ipv4_dst=None, ipv4_dst_mask=None, tcp_src=None, tcp_dst=None, mpls_label=None, mpls_tc=None, metadata=None, metadata_mask=None):
+        if in_port != None:
+            self.in_port = in_port
+        else:
+            self.in_port = 0
+        if wildcards != None:
+            self.wildcards = wildcards
+        else:
+            self.wildcards = const.OFPFW_ALL
+        if eth_src != None:
+            self.eth_src = eth_src
+        else:
+            self.eth_src = [0,0,0,0,0,0]
+        if eth_src_mask != None:
+            self.eth_src_mask = eth_src_mask
+        else:
+            self.eth_src_mask = [0,0,0,0,0,0]
+        if eth_dst != None:
+            self.eth_dst = eth_dst
+        else:
+            self.eth_dst = [0,0,0,0,0,0]
+        if eth_dst_mask != None:
+            self.eth_dst_mask = eth_dst_mask
+        else:
+            self.eth_dst_mask = [0,0,0,0,0,0]
+        if vlan_vid != None:
+            self.vlan_vid = vlan_vid
+        else:
+            self.vlan_vid = 0
+        if vlan_pcp != None:
+            self.vlan_pcp = vlan_pcp
+        else:
+            self.vlan_pcp = 0
+        if eth_type != None:
+            self.eth_type = eth_type
+        else:
+            self.eth_type = 0
+        if ip_dscp != None:
+            self.ip_dscp = ip_dscp
+        else:
+            self.ip_dscp = 0
+        if ip_proto != None:
+            self.ip_proto = ip_proto
+        else:
+            self.ip_proto = 0
+        if ipv4_src != None:
+            self.ipv4_src = ipv4_src
+        else:
+            self.ipv4_src = 0
+        if ipv4_src_mask != None:
+            self.ipv4_src_mask = ipv4_src_mask
+        else:
+            self.ipv4_src_mask = 0
+        if ipv4_dst != None:
+            self.ipv4_dst = ipv4_dst
+        else:
+            self.ipv4_dst = 0
+        if ipv4_dst_mask != None:
+            self.ipv4_dst_mask = ipv4_dst_mask
+        else:
+            self.ipv4_dst_mask = 0
+        if tcp_src != None:
+            self.tcp_src = tcp_src
+        else:
+            self.tcp_src = 0
+        if tcp_dst != None:
+            self.tcp_dst = tcp_dst
+        else:
+            self.tcp_dst = 0
+        if mpls_label != None:
+            self.mpls_label = mpls_label
+        else:
+            self.mpls_label = 0
+        if mpls_tc != None:
+            self.mpls_tc = mpls_tc
+        else:
+            self.mpls_tc = 0
+        if metadata != None:
+            self.metadata = metadata
+        else:
+            self.metadata = 0
+        if metadata_mask != None:
+            self.metadata_mask = metadata_mask
+        else:
+            self.metadata_mask = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 1
+        packed.append(struct.pack("!L", self.in_port))
+        packed.append(struct.pack("!L", self.wildcards))
+        packed.append(struct.pack("!6B", *self.eth_src))
+        packed.append(struct.pack("!6B", *self.eth_src_mask))
+        packed.append(struct.pack("!6B", *self.eth_dst))
+        packed.append(struct.pack("!6B", *self.eth_dst_mask))
+        packed.append(struct.pack("!H", self.vlan_vid))
+        packed.append(struct.pack("!B", self.vlan_pcp))
+        packed.append('\x00' * 1)
+        packed.append(struct.pack("!H", self.eth_type))
+        packed.append(struct.pack("!B", self.ip_dscp))
+        packed.append(struct.pack("!B", self.ip_proto))
+        packed.append(struct.pack("!L", self.ipv4_src))
+        packed.append(struct.pack("!L", self.ipv4_src_mask))
+        packed.append(struct.pack("!L", self.ipv4_dst))
+        packed.append(struct.pack("!L", self.ipv4_dst_mask))
+        packed.append(struct.pack("!H", self.tcp_src))
+        packed.append(struct.pack("!H", self.tcp_dst))
+        packed.append(struct.pack("!L", self.mpls_label))
+        packed.append(struct.pack("!B", self.mpls_tc))
+        packed.append('\x00' * 3)
+        packed.append(struct.pack("!Q", self.metadata))
+        packed.append(struct.pack("!Q", self.metadata_mask))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = match_v2()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == 0)
+        _length = reader.read('!H')[0]
+        obj.in_port = reader.read('!L')[0]
+        obj.wildcards = reader.read('!L')[0]
+        obj.eth_src = list(reader.read('!6B'))
+        obj.eth_src_mask = list(reader.read('!6B'))
+        obj.eth_dst = list(reader.read('!6B'))
+        obj.eth_dst_mask = list(reader.read('!6B'))
+        obj.vlan_vid = reader.read('!H')[0]
+        obj.vlan_pcp = reader.read('!B')[0]
+        reader.skip(1)
+        obj.eth_type = reader.read('!H')[0]
+        obj.ip_dscp = reader.read('!B')[0]
+        obj.ip_proto = reader.read('!B')[0]
+        obj.ipv4_src = reader.read('!L')[0]
+        obj.ipv4_src_mask = reader.read('!L')[0]
+        obj.ipv4_dst = reader.read('!L')[0]
+        obj.ipv4_dst_mask = reader.read('!L')[0]
+        obj.tcp_src = reader.read('!H')[0]
+        obj.tcp_dst = reader.read('!H')[0]
+        obj.mpls_label = reader.read('!L')[0]
+        obj.mpls_tc = reader.read('!B')[0]
+        reader.skip(3)
+        obj.metadata = reader.read('!Q')[0]
+        obj.metadata_mask = reader.read('!Q')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.in_port != other.in_port: return False
+        if self.wildcards != other.wildcards: return False
+        if self.eth_src != other.eth_src: return False
+        if self.eth_src_mask != other.eth_src_mask: return False
+        if self.eth_dst != other.eth_dst: return False
+        if self.eth_dst_mask != other.eth_dst_mask: return False
+        if self.vlan_vid != other.vlan_vid: return False
+        if self.vlan_pcp != other.vlan_pcp: return False
+        if self.eth_type != other.eth_type: return False
+        if self.ip_dscp != other.ip_dscp: return False
+        if self.ip_proto != other.ip_proto: return False
+        if self.ipv4_src != other.ipv4_src: return False
+        if self.ipv4_src_mask != other.ipv4_src_mask: return False
+        if self.ipv4_dst != other.ipv4_dst: return False
+        if self.ipv4_dst_mask != other.ipv4_dst_mask: return False
+        if self.tcp_src != other.tcp_src: return False
+        if self.tcp_dst != other.tcp_dst: return False
+        if self.mpls_label != other.mpls_label: return False
+        if self.mpls_tc != other.mpls_tc: return False
+        if self.metadata != other.metadata: return False
+        if self.metadata_mask != other.metadata_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("match_v2 {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("in_port = ");
+                q.text(util.pretty_port(self.in_port))
+                q.text(","); q.breakable()
+                q.text("wildcards = ");
+                q.text(util.pretty_wildcards(self.wildcards))
+                q.text(","); q.breakable()
+                q.text("eth_src = ");
+                q.text(util.pretty_mac(self.eth_src))
+                q.text(","); q.breakable()
+                q.text("eth_src_mask = ");
+                q.text(util.pretty_mac(self.eth_src_mask))
+                q.text(","); q.breakable()
+                q.text("eth_dst = ");
+                q.text(util.pretty_mac(self.eth_dst))
+                q.text(","); q.breakable()
+                q.text("eth_dst_mask = ");
+                q.text(util.pretty_mac(self.eth_dst_mask))
+                q.text(","); q.breakable()
+                q.text("vlan_vid = ");
+                q.text("%#x" % self.vlan_vid)
+                q.text(","); q.breakable()
+                q.text("vlan_pcp = ");
+                q.text("%#x" % self.vlan_pcp)
+                q.text(","); q.breakable()
+                q.text("eth_type = ");
+                q.text("%#x" % self.eth_type)
+                q.text(","); q.breakable()
+                q.text("ip_dscp = ");
+                q.text("%#x" % self.ip_dscp)
+                q.text(","); q.breakable()
+                q.text("ip_proto = ");
+                q.text("%#x" % self.ip_proto)
+                q.text(","); q.breakable()
+                q.text("ipv4_src = ");
+                q.text(util.pretty_ipv4(self.ipv4_src))
+                q.text(","); q.breakable()
+                q.text("ipv4_src_mask = ");
+                q.text(util.pretty_ipv4(self.ipv4_src_mask))
+                q.text(","); q.breakable()
+                q.text("ipv4_dst = ");
+                q.text(util.pretty_ipv4(self.ipv4_dst))
+                q.text(","); q.breakable()
+                q.text("ipv4_dst_mask = ");
+                q.text(util.pretty_ipv4(self.ipv4_dst_mask))
+                q.text(","); q.breakable()
+                q.text("tcp_src = ");
+                q.text("%#x" % self.tcp_src)
+                q.text(","); q.breakable()
+                q.text("tcp_dst = ");
+                q.text("%#x" % self.tcp_dst)
+                q.text(","); q.breakable()
+                q.text("mpls_label = ");
+                q.text("%#x" % self.mpls_label)
+                q.text(","); q.breakable()
+                q.text("mpls_tc = ");
+                q.text("%#x" % self.mpls_tc)
+                q.text(","); q.breakable()
+                q.text("metadata = ");
+                q.text("%#x" % self.metadata)
+                q.text(","); q.breakable()
+                q.text("metadata_mask = ");
+                q.text("%#x" % self.metadata_mask)
+            q.breakable()
+        q.text('}')
+
+class packet_queue(object):
+
+    def __init__(self, queue_id=None, properties=None):
+        if queue_id != None:
+            self.queue_id = queue_id
+        else:
+            self.queue_id = 0
+        if properties != None:
+            self.properties = properties
+        else:
+            self.properties = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.queue_id))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 2)
+        packed.append("".join([x.pack() for x in self.properties]))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = packet_queue()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.queue_id = reader.read('!L')[0]
+        _len = reader.read('!H')[0]
+        reader.skip(2)
+        obj.properties = common.unpack_list_queue_prop(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.queue_id != other.queue_id: return False
+        if self.properties != other.properties: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("packet_queue {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("queue_id = ");
+                q.text("%#x" % self.queue_id)
+                q.text(","); q.breakable()
+                q.text("properties = ");
+                q.pp(self.properties)
+            q.breakable()
+        q.text('}')
+
+class port_desc(object):
+
+    def __init__(self, port_no=None, hw_addr=None, name=None, config=None, state=None, curr=None, advertised=None, supported=None, peer=None, curr_speed=None, max_speed=None):
+        if port_no != None:
+            self.port_no = port_no
+        else:
+            self.port_no = 0
+        if hw_addr != None:
+            self.hw_addr = hw_addr
+        else:
+            self.hw_addr = [0,0,0,0,0,0]
+        if name != None:
+            self.name = name
+        else:
+            self.name = ""
+        if config != None:
+            self.config = config
+        else:
+            self.config = 0
+        if state != None:
+            self.state = state
+        else:
+            self.state = 0
+        if curr != None:
+            self.curr = curr
+        else:
+            self.curr = 0
+        if advertised != None:
+            self.advertised = advertised
+        else:
+            self.advertised = 0
+        if supported != None:
+            self.supported = supported
+        else:
+            self.supported = 0
+        if peer != None:
+            self.peer = peer
+        else:
+            self.peer = 0
+        if curr_speed != None:
+            self.curr_speed = curr_speed
+        else:
+            self.curr_speed = 0
+        if max_speed != None:
+            self.max_speed = max_speed
+        else:
+            self.max_speed = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.port_no))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!6B", *self.hw_addr))
+        packed.append('\x00' * 2)
+        packed.append(struct.pack("!16s", self.name))
+        packed.append(struct.pack("!L", self.config))
+        packed.append(struct.pack("!L", self.state))
+        packed.append(struct.pack("!L", self.curr))
+        packed.append(struct.pack("!L", self.advertised))
+        packed.append(struct.pack("!L", self.supported))
+        packed.append(struct.pack("!L", self.peer))
+        packed.append(struct.pack("!L", self.curr_speed))
+        packed.append(struct.pack("!L", self.max_speed))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = port_desc()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.port_no = reader.read('!L')[0]
+        reader.skip(4)
+        obj.hw_addr = list(reader.read('!6B'))
+        reader.skip(2)
+        obj.name = reader.read("!16s")[0].rstrip("\x00")
+        obj.config = reader.read('!L')[0]
+        obj.state = reader.read('!L')[0]
+        obj.curr = reader.read('!L')[0]
+        obj.advertised = reader.read('!L')[0]
+        obj.supported = reader.read('!L')[0]
+        obj.peer = reader.read('!L')[0]
+        obj.curr_speed = reader.read('!L')[0]
+        obj.max_speed = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.port_no != other.port_no: return False
+        if self.hw_addr != other.hw_addr: return False
+        if self.name != other.name: return False
+        if self.config != other.config: return False
+        if self.state != other.state: return False
+        if self.curr != other.curr: return False
+        if self.advertised != other.advertised: return False
+        if self.supported != other.supported: return False
+        if self.peer != other.peer: return False
+        if self.curr_speed != other.curr_speed: return False
+        if self.max_speed != other.max_speed: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("port_desc {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("port_no = ");
+                q.text(util.pretty_port(self.port_no))
+                q.text(","); q.breakable()
+                q.text("hw_addr = ");
+                q.text(util.pretty_mac(self.hw_addr))
+                q.text(","); q.breakable()
+                q.text("name = ");
+                q.pp(self.name)
+                q.text(","); q.breakable()
+                q.text("config = ");
+                q.text("%#x" % self.config)
+                q.text(","); q.breakable()
+                q.text("state = ");
+                q.text("%#x" % self.state)
+                q.text(","); q.breakable()
+                q.text("curr = ");
+                q.text("%#x" % self.curr)
+                q.text(","); q.breakable()
+                q.text("advertised = ");
+                q.text("%#x" % self.advertised)
+                q.text(","); q.breakable()
+                q.text("supported = ");
+                q.text("%#x" % self.supported)
+                q.text(","); q.breakable()
+                q.text("peer = ");
+                q.text("%#x" % self.peer)
+                q.text(","); q.breakable()
+                q.text("curr_speed = ");
+                q.text("%#x" % self.curr_speed)
+                q.text(","); q.breakable()
+                q.text("max_speed = ");
+                q.text("%#x" % self.max_speed)
+            q.breakable()
+        q.text('}')
+
+class port_stats_entry(object):
+
+    def __init__(self, port_no=None, rx_packets=None, tx_packets=None, rx_bytes=None, tx_bytes=None, rx_dropped=None, tx_dropped=None, rx_errors=None, tx_errors=None, rx_frame_err=None, rx_over_err=None, rx_crc_err=None, collisions=None):
+        if port_no != None:
+            self.port_no = port_no
+        else:
+            self.port_no = 0
+        if rx_packets != None:
+            self.rx_packets = rx_packets
+        else:
+            self.rx_packets = 0
+        if tx_packets != None:
+            self.tx_packets = tx_packets
+        else:
+            self.tx_packets = 0
+        if rx_bytes != None:
+            self.rx_bytes = rx_bytes
+        else:
+            self.rx_bytes = 0
+        if tx_bytes != None:
+            self.tx_bytes = tx_bytes
+        else:
+            self.tx_bytes = 0
+        if rx_dropped != None:
+            self.rx_dropped = rx_dropped
+        else:
+            self.rx_dropped = 0
+        if tx_dropped != None:
+            self.tx_dropped = tx_dropped
+        else:
+            self.tx_dropped = 0
+        if rx_errors != None:
+            self.rx_errors = rx_errors
+        else:
+            self.rx_errors = 0
+        if tx_errors != None:
+            self.tx_errors = tx_errors
+        else:
+            self.tx_errors = 0
+        if rx_frame_err != None:
+            self.rx_frame_err = rx_frame_err
+        else:
+            self.rx_frame_err = 0
+        if rx_over_err != None:
+            self.rx_over_err = rx_over_err
+        else:
+            self.rx_over_err = 0
+        if rx_crc_err != None:
+            self.rx_crc_err = rx_crc_err
+        else:
+            self.rx_crc_err = 0
+        if collisions != None:
+            self.collisions = collisions
+        else:
+            self.collisions = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.port_no))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!Q", self.rx_packets))
+        packed.append(struct.pack("!Q", self.tx_packets))
+        packed.append(struct.pack("!Q", self.rx_bytes))
+        packed.append(struct.pack("!Q", self.tx_bytes))
+        packed.append(struct.pack("!Q", self.rx_dropped))
+        packed.append(struct.pack("!Q", self.tx_dropped))
+        packed.append(struct.pack("!Q", self.rx_errors))
+        packed.append(struct.pack("!Q", self.tx_errors))
+        packed.append(struct.pack("!Q", self.rx_frame_err))
+        packed.append(struct.pack("!Q", self.rx_over_err))
+        packed.append(struct.pack("!Q", self.rx_crc_err))
+        packed.append(struct.pack("!Q", self.collisions))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = port_stats_entry()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.port_no = reader.read('!L')[0]
+        reader.skip(4)
+        obj.rx_packets = reader.read('!Q')[0]
+        obj.tx_packets = reader.read('!Q')[0]
+        obj.rx_bytes = reader.read('!Q')[0]
+        obj.tx_bytes = reader.read('!Q')[0]
+        obj.rx_dropped = reader.read('!Q')[0]
+        obj.tx_dropped = reader.read('!Q')[0]
+        obj.rx_errors = reader.read('!Q')[0]
+        obj.tx_errors = reader.read('!Q')[0]
+        obj.rx_frame_err = reader.read('!Q')[0]
+        obj.rx_over_err = reader.read('!Q')[0]
+        obj.rx_crc_err = reader.read('!Q')[0]
+        obj.collisions = reader.read('!Q')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.port_no != other.port_no: return False
+        if self.rx_packets != other.rx_packets: return False
+        if self.tx_packets != other.tx_packets: return False
+        if self.rx_bytes != other.rx_bytes: return False
+        if self.tx_bytes != other.tx_bytes: return False
+        if self.rx_dropped != other.rx_dropped: return False
+        if self.tx_dropped != other.tx_dropped: return False
+        if self.rx_errors != other.rx_errors: return False
+        if self.tx_errors != other.tx_errors: return False
+        if self.rx_frame_err != other.rx_frame_err: return False
+        if self.rx_over_err != other.rx_over_err: return False
+        if self.rx_crc_err != other.rx_crc_err: return False
+        if self.collisions != other.collisions: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("port_stats_entry {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("port_no = ");
+                q.text(util.pretty_port(self.port_no))
+                q.text(","); q.breakable()
+                q.text("rx_packets = ");
+                q.text("%#x" % self.rx_packets)
+                q.text(","); q.breakable()
+                q.text("tx_packets = ");
+                q.text("%#x" % self.tx_packets)
+                q.text(","); q.breakable()
+                q.text("rx_bytes = ");
+                q.text("%#x" % self.rx_bytes)
+                q.text(","); q.breakable()
+                q.text("tx_bytes = ");
+                q.text("%#x" % self.tx_bytes)
+                q.text(","); q.breakable()
+                q.text("rx_dropped = ");
+                q.text("%#x" % self.rx_dropped)
+                q.text(","); q.breakable()
+                q.text("tx_dropped = ");
+                q.text("%#x" % self.tx_dropped)
+                q.text(","); q.breakable()
+                q.text("rx_errors = ");
+                q.text("%#x" % self.rx_errors)
+                q.text(","); q.breakable()
+                q.text("tx_errors = ");
+                q.text("%#x" % self.tx_errors)
+                q.text(","); q.breakable()
+                q.text("rx_frame_err = ");
+                q.text("%#x" % self.rx_frame_err)
+                q.text(","); q.breakable()
+                q.text("rx_over_err = ");
+                q.text("%#x" % self.rx_over_err)
+                q.text(","); q.breakable()
+                q.text("rx_crc_err = ");
+                q.text("%#x" % self.rx_crc_err)
+                q.text(","); q.breakable()
+                q.text("collisions = ");
+                q.text("%#x" % self.collisions)
+            q.breakable()
+        q.text('}')
+
+class queue_prop_min_rate(object):
+    type = const.OFPQT_MIN_RATE
+
+    def __init__(self, rate=None):
+        if rate != None:
+            self.rate = rate
+        else:
+            self.rate = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!H", self.rate))
+        packed.append('\x00' * 6)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = queue_prop_min_rate()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPQT_MIN_RATE)
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        obj.rate = reader.read('!H')[0]
+        reader.skip(6)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.rate != other.rate: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("queue_prop_min_rate {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("rate = ");
+                q.text("%#x" % self.rate)
+            q.breakable()
+        q.text('}')
+
+class queue_stats_entry(object):
+
+    def __init__(self, port_no=None, queue_id=None, tx_bytes=None, tx_packets=None, tx_errors=None):
+        if port_no != None:
+            self.port_no = port_no
+        else:
+            self.port_no = 0
+        if queue_id != None:
+            self.queue_id = queue_id
+        else:
+            self.queue_id = 0
+        if tx_bytes != None:
+            self.tx_bytes = tx_bytes
+        else:
+            self.tx_bytes = 0
+        if tx_packets != None:
+            self.tx_packets = tx_packets
+        else:
+            self.tx_packets = 0
+        if tx_errors != None:
+            self.tx_errors = tx_errors
+        else:
+            self.tx_errors = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.port_no))
+        packed.append(struct.pack("!L", self.queue_id))
+        packed.append(struct.pack("!Q", self.tx_bytes))
+        packed.append(struct.pack("!Q", self.tx_packets))
+        packed.append(struct.pack("!Q", self.tx_errors))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = queue_stats_entry()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.port_no = reader.read('!L')[0]
+        obj.queue_id = reader.read('!L')[0]
+        obj.tx_bytes = reader.read('!Q')[0]
+        obj.tx_packets = reader.read('!Q')[0]
+        obj.tx_errors = reader.read('!Q')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.port_no != other.port_no: return False
+        if self.queue_id != other.queue_id: return False
+        if self.tx_bytes != other.tx_bytes: return False
+        if self.tx_packets != other.tx_packets: return False
+        if self.tx_errors != other.tx_errors: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("queue_stats_entry {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("port_no = ");
+                q.text(util.pretty_port(self.port_no))
+                q.text(","); q.breakable()
+                q.text("queue_id = ");
+                q.text("%#x" % self.queue_id)
+                q.text(","); q.breakable()
+                q.text("tx_bytes = ");
+                q.text("%#x" % self.tx_bytes)
+                q.text(","); q.breakable()
+                q.text("tx_packets = ");
+                q.text("%#x" % self.tx_packets)
+                q.text(","); q.breakable()
+                q.text("tx_errors = ");
+                q.text("%#x" % self.tx_errors)
+            q.breakable()
+        q.text('}')
+
+class table_stats_entry(object):
+
+    def __init__(self, table_id=None, name=None, wildcards=None, match=None, instructions=None, write_actions=None, apply_actions=None, config=None, max_entries=None, active_count=None, lookup_count=None, matched_count=None):
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if name != None:
+            self.name = name
+        else:
+            self.name = ""
+        if wildcards != None:
+            self.wildcards = wildcards
+        else:
+            self.wildcards = const.OFPFW_ALL
+        if match != None:
+            self.match = match
+        else:
+            self.match = const.OFPFW_ALL
+        if instructions != None:
+            self.instructions = instructions
+        else:
+            self.instructions = 0
+        if write_actions != None:
+            self.write_actions = write_actions
+        else:
+            self.write_actions = 0
+        if apply_actions != None:
+            self.apply_actions = apply_actions
+        else:
+            self.apply_actions = 0
+        if config != None:
+            self.config = config
+        else:
+            self.config = 0
+        if max_entries != None:
+            self.max_entries = max_entries
+        else:
+            self.max_entries = 0
+        if active_count != None:
+            self.active_count = active_count
+        else:
+            self.active_count = 0
+        if lookup_count != None:
+            self.lookup_count = lookup_count
+        else:
+            self.lookup_count = 0
+        if matched_count != None:
+            self.matched_count = matched_count
+        else:
+            self.matched_count = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append('\x00' * 7)
+        packed.append(struct.pack("!32s", self.name))
+        packed.append(struct.pack("!L", self.wildcards))
+        packed.append(struct.pack("!L", self.match))
+        packed.append(struct.pack("!L", self.instructions))
+        packed.append(struct.pack("!L", self.write_actions))
+        packed.append(struct.pack("!L", self.apply_actions))
+        packed.append(struct.pack("!L", self.config))
+        packed.append(struct.pack("!L", self.max_entries))
+        packed.append(struct.pack("!L", self.active_count))
+        packed.append(struct.pack("!Q", self.lookup_count))
+        packed.append(struct.pack("!Q", self.matched_count))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = table_stats_entry()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.table_id = reader.read('!B')[0]
+        reader.skip(7)
+        obj.name = reader.read("!32s")[0].rstrip("\x00")
+        obj.wildcards = reader.read('!L')[0]
+        obj.match = reader.read('!L')[0]
+        obj.instructions = reader.read('!L')[0]
+        obj.write_actions = reader.read('!L')[0]
+        obj.apply_actions = reader.read('!L')[0]
+        obj.config = reader.read('!L')[0]
+        obj.max_entries = reader.read('!L')[0]
+        obj.active_count = reader.read('!L')[0]
+        obj.lookup_count = reader.read('!Q')[0]
+        obj.matched_count = reader.read('!Q')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.table_id != other.table_id: return False
+        if self.name != other.name: return False
+        if self.wildcards != other.wildcards: return False
+        if self.match != other.match: return False
+        if self.instructions != other.instructions: return False
+        if self.write_actions != other.write_actions: return False
+        if self.apply_actions != other.apply_actions: return False
+        if self.config != other.config: return False
+        if self.max_entries != other.max_entries: return False
+        if self.active_count != other.active_count: return False
+        if self.lookup_count != other.lookup_count: return False
+        if self.matched_count != other.matched_count: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_stats_entry {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("name = ");
+                q.pp(self.name)
+                q.text(","); q.breakable()
+                q.text("wildcards = ");
+                q.text(util.pretty_wildcards(self.wildcards))
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+                q.text(","); q.breakable()
+                q.text("instructions = ");
+                q.text("%#x" % self.instructions)
+                q.text(","); q.breakable()
+                q.text("write_actions = ");
+                q.text("%#x" % self.write_actions)
+                q.text(","); q.breakable()
+                q.text("apply_actions = ");
+                q.text("%#x" % self.apply_actions)
+                q.text(","); q.breakable()
+                q.text("config = ");
+                q.text("%#x" % self.config)
+                q.text(","); q.breakable()
+                q.text("max_entries = ");
+                q.text("%#x" % self.max_entries)
+                q.text(","); q.breakable()
+                q.text("active_count = ");
+                q.text("%#x" % self.active_count)
+                q.text(","); q.breakable()
+                q.text("lookup_count = ");
+                q.text("%#x" % self.lookup_count)
+                q.text(","); q.breakable()
+                q.text("matched_count = ");
+                q.text("%#x" % self.matched_count)
+            q.breakable()
+        q.text('}')
+
+
+match = match_v2
diff --git a/src/python/loxi/of11/const.py b/src/python/loxi/of11/const.py
new file mode 100644
index 0000000..b6cca94
--- /dev/null
+++ b/src/python/loxi/of11/const.py
@@ -0,0 +1,679 @@
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+
+# Automatically generated by LOXI from template const.py
+# Do not modify
+
+OFP_VERSION = 2
+
+# Identifiers from group macro_definitions
+OFP_VLAN_NONE = 0
+OFP_FLOW_PERMANENT = 0
+OFP_ETH_ALEN = 6
+OFP_MAX_PORT_NAME_LEN = 16
+OFP_MAX_TABLE_NAME_LEN = 32
+SERIAL_NUM_LEN = 32
+OFPFW_ICMP_TYPE = 64
+OFPMT_STANDARD_LENGTH = 88
+OFP_DEFAULT_MISS_SEND_LEN = 128
+OFPFW_ICMP_CODE = 128
+DESC_STR_LEN = 256
+OFP_DL_TYPE_NOT_ETH_TYPE = 1535
+OFP_DL_TYPE_ETH2_CUTOFF = 1536
+OFP_TCP_PORT = 6633
+OFP_SSL_PORT = 6633
+OFP_DEFAULT_PRIORITY = 32768
+OFPQ_MIN_RATE_UNCFG = 65535
+OFPQ_ALL = 4294967295
+
+# Identifiers from group ofp_action_type
+OFPAT_OUTPUT = 0
+OFPAT_SET_VLAN_VID = 1
+OFPAT_SET_VLAN_PCP = 2
+OFPAT_SET_DL_SRC = 3
+OFPAT_SET_DL_DST = 4
+OFPAT_SET_NW_SRC = 5
+OFPAT_SET_NW_DST = 6
+OFPAT_SET_NW_TOS = 7
+OFPAT_SET_NW_ECN = 8
+OFPAT_SET_TP_SRC = 9
+OFPAT_SET_TP_DST = 10
+OFPAT_COPY_TTL_OUT = 11
+OFPAT_COPY_TTL_IN = 12
+OFPAT_SET_MPLS_LABEL = 13
+OFPAT_SET_MPLS_TC = 14
+OFPAT_SET_MPLS_TTL = 15
+OFPAT_DEC_MPLS_TTL = 16
+OFPAT_PUSH_VLAN = 17
+OFPAT_POP_VLAN = 18
+OFPAT_PUSH_MPLS = 19
+OFPAT_POP_MPLS = 20
+OFPAT_SET_QUEUE = 21
+OFPAT_GROUP = 22
+OFPAT_SET_NW_TTL = 23
+OFPAT_DEC_NW_TTL = 24
+OFPAT_EXPERIMENTER = 65535
+
+ofp_action_type_map = {
+    0: 'OFPAT_OUTPUT',
+    1: 'OFPAT_SET_VLAN_VID',
+    2: 'OFPAT_SET_VLAN_PCP',
+    3: 'OFPAT_SET_DL_SRC',
+    4: 'OFPAT_SET_DL_DST',
+    5: 'OFPAT_SET_NW_SRC',
+    6: 'OFPAT_SET_NW_DST',
+    7: 'OFPAT_SET_NW_TOS',
+    8: 'OFPAT_SET_NW_ECN',
+    9: 'OFPAT_SET_TP_SRC',
+    10: 'OFPAT_SET_TP_DST',
+    11: 'OFPAT_COPY_TTL_OUT',
+    12: 'OFPAT_COPY_TTL_IN',
+    13: 'OFPAT_SET_MPLS_LABEL',
+    14: 'OFPAT_SET_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',
+    65535: 'OFPAT_EXPERIMENTER',
+}
+
+# Identifiers from group ofp_bad_action_code
+OFPBAC_BAD_TYPE = 0
+OFPBAC_BAD_LEN = 1
+OFPBAC_BAD_EXPERIMENTER = 2
+OFPBAC_BAD_EXPERIMENTER_TYPE = 3
+OFPBAC_BAD_OUT_PORT = 4
+OFPBAC_BAD_ARGUMENT = 5
+OFPBAC_EPERM = 6
+OFPBAC_TOO_MANY = 7
+OFPBAC_BAD_QUEUE = 8
+OFPBAC_BAD_OUT_GROUP = 9
+OFPBAC_MATCH_INCONSISTENT = 10
+OFPBAC_UNSUPPORTED_ORDER = 11
+OFPBAC_BAD_TAG = 12
+
+ofp_bad_action_code_map = {
+    0: 'OFPBAC_BAD_TYPE',
+    1: 'OFPBAC_BAD_LEN',
+    2: 'OFPBAC_BAD_EXPERIMENTER',
+    3: 'OFPBAC_BAD_EXPERIMENTER_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',
+}
+
+# Identifiers from group ofp_bad_instruction_code
+OFPBIC_UNKNOWN_INST = 0
+OFPBIC_UNSUP_INST = 1
+OFPBIC_BAD_TABLE_ID = 2
+OFPBIC_UNSUP_METADATA = 3
+OFPBIC_UNSUP_METADATA_MASK = 4
+OFPBIC_UNSUP_EXP_INST = 5
+
+ofp_bad_instruction_code_map = {
+    0: 'OFPBIC_UNKNOWN_INST',
+    1: 'OFPBIC_UNSUP_INST',
+    2: 'OFPBIC_BAD_TABLE_ID',
+    3: 'OFPBIC_UNSUP_METADATA',
+    4: 'OFPBIC_UNSUP_METADATA_MASK',
+    5: 'OFPBIC_UNSUP_EXP_INST',
+}
+
+# Identifiers from group ofp_bad_match_code
+OFPBMC_BAD_TYPE = 0
+OFPBMC_BAD_LEN = 1
+OFPBMC_BAD_TAG = 2
+OFPBMC_BAD_DL_ADDR_MASK = 3
+OFPBMC_BAD_NW_ADDR_MASK = 4
+OFPBMC_BAD_WILDCARDS = 5
+OFPBMC_BAD_FIELD = 6
+OFPBMC_BAD_VALUE = 7
+
+ofp_bad_match_code_map = {
+    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',
+}
+
+# Identifiers from group ofp_bad_request_code
+OFPBRC_BAD_VERSION = 0
+OFPBRC_BAD_TYPE = 1
+OFPBRC_BAD_STAT = 2
+OFPBRC_BAD_EXPERIMENTER = 3
+OFPBRC_BAD_SUBTYPE = 4
+OFPBRC_EPERM = 5
+OFPBRC_BAD_LEN = 6
+OFPBRC_BUFFER_EMPTY = 7
+OFPBRC_BUFFER_UNKNOWN = 8
+OFPBRC_BAD_TABLE_ID = 9
+
+ofp_bad_request_code_map = {
+    0: 'OFPBRC_BAD_VERSION',
+    1: 'OFPBRC_BAD_TYPE',
+    2: 'OFPBRC_BAD_STAT',
+    3: 'OFPBRC_BAD_EXPERIMENTER',
+    4: 'OFPBRC_BAD_SUBTYPE',
+    5: 'OFPBRC_EPERM',
+    6: 'OFPBRC_BAD_LEN',
+    7: 'OFPBRC_BUFFER_EMPTY',
+    8: 'OFPBRC_BUFFER_UNKNOWN',
+    9: 'OFPBRC_BAD_TABLE_ID',
+}
+
+# Identifiers from group ofp_capabilities
+OFPC_FLOW_STATS = 1
+OFPC_TABLE_STATS = 2
+OFPC_PORT_STATS = 4
+OFPC_GROUP_STATS = 8
+OFPC_IP_REASM = 32
+OFPC_QUEUE_STATS = 64
+OFPC_ARP_MATCH_IP = 128
+
+ofp_capabilities_map = {
+    1: 'OFPC_FLOW_STATS',
+    2: 'OFPC_TABLE_STATS',
+    4: 'OFPC_PORT_STATS',
+    8: 'OFPC_GROUP_STATS',
+    32: 'OFPC_IP_REASM',
+    64: 'OFPC_QUEUE_STATS',
+    128: 'OFPC_ARP_MATCH_IP',
+}
+
+# Identifiers from group ofp_config_flags
+OFPC_FRAG_NORMAL = 0
+OFPC_FRAG_DROP = 1
+OFPC_FRAG_REASM = 2
+OFPC_FRAG_MASK = 3
+OFPC_INVALID_TTL_TO_CONTROLLER = 4
+
+ofp_config_flags_map = {
+    0: 'OFPC_FRAG_NORMAL',
+    1: 'OFPC_FRAG_DROP',
+    2: 'OFPC_FRAG_REASM',
+    3: 'OFPC_FRAG_MASK',
+    4: 'OFPC_INVALID_TTL_TO_CONTROLLER',
+}
+
+# Identifiers from group ofp_error_type
+OFPET_HELLO_FAILED = 0
+OFPET_BAD_REQUEST = 1
+OFPET_BAD_ACTION = 2
+OFPET_BAD_INSTRUCTION = 3
+OFPET_BAD_MATCH = 4
+OFPET_FLOW_MOD_FAILED = 5
+OFPET_GROUP_MOD_FAILED = 6
+OFPET_PORT_MOD_FAILED = 7
+OFPET_TABLE_MOD_FAILED = 8
+OFPET_QUEUE_OP_FAILED = 9
+OFPET_SWITCH_CONFIG_FAILED = 10
+
+ofp_error_type_map = {
+    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',
+}
+
+# Identifiers from group ofp_flow_mod_command
+OFPFC_ADD = 0
+OFPFC_MODIFY = 1
+OFPFC_MODIFY_STRICT = 2
+OFPFC_DELETE = 3
+OFPFC_DELETE_STRICT = 4
+
+ofp_flow_mod_command_map = {
+    0: 'OFPFC_ADD',
+    1: 'OFPFC_MODIFY',
+    2: 'OFPFC_MODIFY_STRICT',
+    3: 'OFPFC_DELETE',
+    4: 'OFPFC_DELETE_STRICT',
+}
+
+# Identifiers from group ofp_flow_mod_failed_code
+OFPFMFC_UNKNOWN = 0
+OFPFMFC_TABLE_FULL = 1
+OFPFMFC_BAD_TABLE_ID = 2
+OFPFMFC_OVERLAP = 3
+OFPFMFC_EPERM = 4
+OFPFMFC_BAD_TIMEOUT = 5
+OFPFMFC_BAD_COMMAND = 6
+
+ofp_flow_mod_failed_code_map = {
+    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',
+}
+
+# Identifiers from group ofp_flow_mod_flags
+OFPFF_SEND_FLOW_REM = 1
+OFPFF_CHECK_OVERLAP = 2
+
+ofp_flow_mod_flags_map = {
+    1: 'OFPFF_SEND_FLOW_REM',
+    2: 'OFPFF_CHECK_OVERLAP',
+}
+
+# Identifiers from group ofp_flow_removed_reason
+OFPRR_IDLE_TIMEOUT = 0
+OFPRR_HARD_TIMEOUT = 1
+OFPRR_DELETE = 2
+OFPRR_GROUP_DELETE = 3
+
+ofp_flow_removed_reason_map = {
+    0: 'OFPRR_IDLE_TIMEOUT',
+    1: 'OFPRR_HARD_TIMEOUT',
+    2: 'OFPRR_DELETE',
+    3: 'OFPRR_GROUP_DELETE',
+}
+
+# Identifiers from group ofp_flow_wildcards
+OFPFW_IN_PORT = 1
+OFPFW_DL_VLAN = 2
+OFPFW_DL_VLAN_PCP = 4
+OFPFW_DL_TYPE = 8
+OFPFW_NW_TOS = 16
+OFPFW_NW_PROTO = 32
+OFPFW_TP_SRC = 64
+OFPFW_TP_DST = 128
+OFPFW_MPLS_LABEL = 256
+OFPFW_MPLS_TC = 512
+OFPFW_ALL = 1023
+
+ofp_flow_wildcards_map = {
+    1: 'OFPFW_IN_PORT',
+    2: 'OFPFW_DL_VLAN',
+    4: 'OFPFW_DL_VLAN_PCP',
+    8: 'OFPFW_DL_TYPE',
+    16: 'OFPFW_NW_TOS',
+    32: 'OFPFW_NW_PROTO',
+    64: 'OFPFW_TP_SRC',
+    128: 'OFPFW_TP_DST',
+    256: 'OFPFW_MPLS_LABEL',
+    512: 'OFPFW_MPLS_TC',
+}
+
+# Identifiers from group ofp_group
+OFPG_MAX = 4294967040
+OFPG_ALL = 4294967292
+OFPG_ANY = 4294967295
+
+ofp_group_map = {
+    4294967040: 'OFPG_MAX',
+    4294967292: 'OFPG_ALL',
+    4294967295: 'OFPG_ANY',
+}
+
+# Identifiers from group ofp_group_mod_command
+OFPGC_ADD = 0
+OFPGC_MODIFY = 1
+OFPGC_DELETE = 2
+
+ofp_group_mod_command_map = {
+    0: 'OFPGC_ADD',
+    1: 'OFPGC_MODIFY',
+    2: 'OFPGC_DELETE',
+}
+
+# Identifiers from group ofp_group_mod_failed_code
+OFPGMFC_GROUP_EXISTS = 0
+OFPGMFC_INVALID_GROUP = 1
+OFPGMFC_WEIGHT_UNSUPPORTED = 2
+OFPGMFC_OUT_OF_GROUPS = 3
+OFPGMFC_OUT_OF_BUCKETS = 4
+OFPGMFC_CHAINING_UNSUPPORTED = 5
+OFPGMFC_WATCH_UNSUPPORTED = 6
+OFPGMFC_LOOP = 7
+OFPGMFC_UNKNOWN_GROUP = 8
+
+ofp_group_mod_failed_code_map = {
+    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',
+}
+
+# Identifiers from group ofp_group_type
+OFPGT_ALL = 0
+OFPGT_SELECT = 1
+OFPGT_INDIRECT = 2
+OFPGT_FF = 3
+
+ofp_group_type_map = {
+    0: 'OFPGT_ALL',
+    1: 'OFPGT_SELECT',
+    2: 'OFPGT_INDIRECT',
+    3: 'OFPGT_FF',
+}
+
+# Identifiers from group ofp_hello_failed_code
+OFPHFC_INCOMPATIBLE = 0
+OFPHFC_EPERM = 1
+
+ofp_hello_failed_code_map = {
+    0: 'OFPHFC_INCOMPATIBLE',
+    1: 'OFPHFC_EPERM',
+}
+
+# Identifiers from group ofp_instruction_type
+OFPIT_GOTO_TABLE = 1
+OFPIT_WRITE_METADATA = 2
+OFPIT_WRITE_ACTIONS = 3
+OFPIT_APPLY_ACTIONS = 4
+OFPIT_CLEAR_ACTIONS = 5
+OFPIT_EXPERIMENTER = 65535
+
+ofp_instruction_type_map = {
+    1: 'OFPIT_GOTO_TABLE',
+    2: 'OFPIT_WRITE_METADATA',
+    3: 'OFPIT_WRITE_ACTIONS',
+    4: 'OFPIT_APPLY_ACTIONS',
+    5: 'OFPIT_CLEAR_ACTIONS',
+    65535: 'OFPIT_EXPERIMENTER',
+}
+
+# Identifiers from group ofp_match_type
+OFPMT_STANDARD = 0
+
+ofp_match_type_map = {
+    0: 'OFPMT_STANDARD',
+}
+
+# Identifiers from group ofp_packet_in_reason
+OFPR_NO_MATCH = 0
+OFPR_ACTION = 1
+
+ofp_packet_in_reason_map = {
+    0: 'OFPR_NO_MATCH',
+    1: 'OFPR_ACTION',
+}
+
+# Identifiers from group ofp_port
+OFPP_MAX = 4294967040
+OFPP_IN_PORT = 4294967288
+OFPP_TABLE = 4294967289
+OFPP_NORMAL = 4294967290
+OFPP_FLOOD = 4294967291
+OFPP_ALL = 4294967292
+OFPP_CONTROLLER = 4294967293
+OFPP_LOCAL = 4294967294
+
+ofp_port_map = {
+    4294967040: 'OFPP_MAX',
+    4294967288: 'OFPP_IN_PORT',
+    4294967289: 'OFPP_TABLE',
+    4294967290: 'OFPP_NORMAL',
+    4294967291: 'OFPP_FLOOD',
+    4294967292: 'OFPP_ALL',
+    4294967293: 'OFPP_CONTROLLER',
+    4294967294: 'OFPP_LOCAL',
+}
+
+# Identifiers from group ofp_port_config
+OFPPC_PORT_DOWN = 1
+OFPPC_NO_RECV = 4
+OFPPC_NO_FWD = 32
+OFPPC_NO_PACKET_IN = 64
+
+ofp_port_config_map = {
+    1: 'OFPPC_PORT_DOWN',
+    4: 'OFPPC_NO_RECV',
+    32: 'OFPPC_NO_FWD',
+    64: 'OFPPC_NO_PACKET_IN',
+}
+
+# Identifiers from group ofp_port_features
+OFPPF_10MB_HD = 1
+OFPPF_10MB_FD = 2
+OFPPF_100MB_HD = 4
+OFPPF_100MB_FD = 8
+OFPPF_1GB_HD = 16
+OFPPF_1GB_FD = 32
+OFPPF_10GB_FD = 64
+OFPPF_40GB_FD = 128
+OFPPF_100GB_FD = 256
+OFPPF_1TB_FD = 512
+OFPPF_OTHER = 1024
+OFPPF_COPPER = 2048
+OFPPF_FIBER = 4096
+OFPPF_AUTONEG = 8192
+OFPPF_PAUSE = 16384
+OFPPF_PAUSE_ASYM = 32768
+
+ofp_port_features_map = {
+    1: 'OFPPF_10MB_HD',
+    2: 'OFPPF_10MB_FD',
+    4: 'OFPPF_100MB_HD',
+    8: 'OFPPF_100MB_FD',
+    16: 'OFPPF_1GB_HD',
+    32: 'OFPPF_1GB_FD',
+    64: 'OFPPF_10GB_FD',
+    128: 'OFPPF_40GB_FD',
+    256: 'OFPPF_100GB_FD',
+    512: 'OFPPF_1TB_FD',
+    1024: 'OFPPF_OTHER',
+    2048: 'OFPPF_COPPER',
+    4096: 'OFPPF_FIBER',
+    8192: 'OFPPF_AUTONEG',
+    16384: 'OFPPF_PAUSE',
+    32768: 'OFPPF_PAUSE_ASYM',
+}
+
+# Identifiers from group ofp_port_mod_failed_code
+OFPPMFC_BAD_PORT = 0
+OFPPMFC_BAD_HW_ADDR = 1
+OFPPMFC_BAD_CONFIG = 2
+OFPPMFC_BAD_ADVERTISE = 3
+
+ofp_port_mod_failed_code_map = {
+    0: 'OFPPMFC_BAD_PORT',
+    1: 'OFPPMFC_BAD_HW_ADDR',
+    2: 'OFPPMFC_BAD_CONFIG',
+    3: 'OFPPMFC_BAD_ADVERTISE',
+}
+
+# Identifiers from group ofp_port_no
+OFPP_ANY = 4294967295
+
+ofp_port_no_map = {
+    4294967295: 'OFPP_ANY',
+}
+
+# Identifiers from group ofp_port_reason
+OFPPR_ADD = 0
+OFPPR_DELETE = 1
+OFPPR_MODIFY = 2
+
+ofp_port_reason_map = {
+    0: 'OFPPR_ADD',
+    1: 'OFPPR_DELETE',
+    2: 'OFPPR_MODIFY',
+}
+
+# Identifiers from group ofp_port_state
+OFPPS_LINK_DOWN = 1
+OFPPS_BLOCKED = 2
+OFPPS_LIVE = 4
+
+ofp_port_state_map = {
+    1: 'OFPPS_LINK_DOWN',
+    2: 'OFPPS_BLOCKED',
+    4: 'OFPPS_LIVE',
+}
+
+# Identifiers from group ofp_queue_op_failed_code
+OFPQOFC_BAD_PORT = 0
+OFPQOFC_BAD_QUEUE = 1
+OFPQOFC_EPERM = 2
+
+ofp_queue_op_failed_code_map = {
+    0: 'OFPQOFC_BAD_PORT',
+    1: 'OFPQOFC_BAD_QUEUE',
+    2: 'OFPQOFC_EPERM',
+}
+
+# Identifiers from group ofp_queue_properties
+OFPQT_NONE = 0
+OFPQT_MIN_RATE = 1
+
+ofp_queue_properties_map = {
+    0: 'OFPQT_NONE',
+    1: 'OFPQT_MIN_RATE',
+}
+
+# Identifiers from group ofp_stats_reply_flags
+OFPSF_REPLY_MORE = 1
+
+ofp_stats_reply_flags_map = {
+    1: 'OFPSF_REPLY_MORE',
+}
+
+# Identifiers from group ofp_stats_types
+OFPST_DESC = 0
+OFPST_FLOW = 1
+OFPST_AGGREGATE = 2
+OFPST_TABLE = 3
+OFPST_PORT = 4
+OFPST_QUEUE = 5
+OFPST_GROUP = 6
+OFPST_GROUP_DESC = 7
+OFPST_EXPERIMENTER = 65535
+
+ofp_stats_types_map = {
+    0: 'OFPST_DESC',
+    1: 'OFPST_FLOW',
+    2: 'OFPST_AGGREGATE',
+    3: 'OFPST_TABLE',
+    4: 'OFPST_PORT',
+    5: 'OFPST_QUEUE',
+    6: 'OFPST_GROUP',
+    7: 'OFPST_GROUP_DESC',
+    65535: 'OFPST_EXPERIMENTER',
+}
+
+# Identifiers from group ofp_switch_config_failed_code
+OFPSCFC_BAD_FLAGS = 0
+OFPSCFC_BAD_LEN = 1
+
+ofp_switch_config_failed_code_map = {
+    0: 'OFPSCFC_BAD_FLAGS',
+    1: 'OFPSCFC_BAD_LEN',
+}
+
+# Identifiers from group ofp_table_config
+OFPTC_TABLE_MISS_CONTROLLER = 0
+OFPTC_TABLE_MISS_CONTINUE = 1
+OFPTC_TABLE_MISS_DROP = 2
+OFPTC_TABLE_MISS_MASK = 3
+
+ofp_table_config_map = {
+    0: 'OFPTC_TABLE_MISS_CONTROLLER',
+    1: 'OFPTC_TABLE_MISS_CONTINUE',
+    2: 'OFPTC_TABLE_MISS_DROP',
+    3: 'OFPTC_TABLE_MISS_MASK',
+}
+
+# Identifiers from group ofp_table_mod_failed_code
+OFPTMFC_BAD_TABLE = 0
+OFPTMFC_BAD_CONFIG = 1
+
+ofp_table_mod_failed_code_map = {
+    0: 'OFPTMFC_BAD_TABLE',
+    1: 'OFPTMFC_BAD_CONFIG',
+}
+
+# Identifiers from group ofp_type
+OFPT_HELLO = 0
+OFPT_ERROR = 1
+OFPT_ECHO_REQUEST = 2
+OFPT_ECHO_REPLY = 3
+OFPT_EXPERIMENTER = 4
+OFPT_FEATURES_REQUEST = 5
+OFPT_FEATURES_REPLY = 6
+OFPT_GET_CONFIG_REQUEST = 7
+OFPT_GET_CONFIG_REPLY = 8
+OFPT_SET_CONFIG = 9
+OFPT_PACKET_IN = 10
+OFPT_FLOW_REMOVED = 11
+OFPT_PORT_STATUS = 12
+OFPT_PACKET_OUT = 13
+OFPT_FLOW_MOD = 14
+OFPT_GROUP_MOD = 15
+OFPT_PORT_MOD = 16
+OFPT_TABLE_MOD = 17
+OFPT_STATS_REQUEST = 18
+OFPT_STATS_REPLY = 19
+OFPT_BARRIER_REQUEST = 20
+OFPT_BARRIER_REPLY = 21
+OFPT_QUEUE_GET_CONFIG_REQUEST = 22
+OFPT_QUEUE_GET_CONFIG_REPLY = 23
+
+ofp_type_map = {
+    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_STATS_REQUEST',
+    19: 'OFPT_STATS_REPLY',
+    20: 'OFPT_BARRIER_REQUEST',
+    21: 'OFPT_BARRIER_REPLY',
+    22: 'OFPT_QUEUE_GET_CONFIG_REQUEST',
+    23: 'OFPT_QUEUE_GET_CONFIG_REPLY',
+}
+
+# Identifiers from group ofp_vlan_id
+OFPVID_ANY = 65534
+OFPVID_NONE = 65535
+
+ofp_vlan_id_map = {
+    65534: 'OFPVID_ANY',
+    65535: 'OFPVID_NONE',
+}
+
diff --git a/src/python/loxi/of11/message.py b/src/python/loxi/of11/message.py
new file mode 100644
index 0000000..6de2b6c
--- /dev/null
+++ b/src/python/loxi/of11/message.py
@@ -0,0 +1,5193 @@
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+
+# Automatically generated by LOXI from template message.py
+# Do not modify
+
+import struct
+import loxi
+import const
+import common
+import action # for unpack_list
+import instruction # for unpack_list
+import util
+import loxi.generic_util
+
+class Message(object):
+    version = const.OFP_VERSION
+    type = None # override in subclass
+    xid = None
+
+class aggregate_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REPLY
+    stats_type = const.OFPST_AGGREGATE
+
+    def __init__(self, xid=None, flags=None, packet_count=None, byte_count=None, flow_count=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if packet_count != None:
+            self.packet_count = packet_count
+        else:
+            self.packet_count = 0
+        if byte_count != None:
+            self.byte_count = byte_count
+        else:
+            self.byte_count = 0
+        if flow_count != None:
+            self.flow_count = flow_count
+        else:
+            self.flow_count = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!Q", self.packet_count))
+        packed.append(struct.pack("!Q", self.byte_count))
+        packed.append(struct.pack("!L", self.flow_count))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = aggregate_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_AGGREGATE)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.packet_count = reader.read('!Q')[0]
+        obj.byte_count = reader.read('!Q')[0]
+        obj.flow_count = reader.read('!L')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.packet_count != other.packet_count: return False
+        if self.byte_count != other.byte_count: return False
+        if self.flow_count != other.flow_count: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("aggregate_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("packet_count = ");
+                q.text("%#x" % self.packet_count)
+                q.text(","); q.breakable()
+                q.text("byte_count = ");
+                q.text("%#x" % self.byte_count)
+                q.text(","); q.breakable()
+                q.text("flow_count = ");
+                q.text("%#x" % self.flow_count)
+            q.breakable()
+        q.text('}')
+
+class aggregate_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REQUEST
+    stats_type = const.OFPST_AGGREGATE
+
+    def __init__(self, xid=None, flags=None, table_id=None, out_port=None, out_group=None, cookie=None, cookie_mask=None, match=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if out_port != None:
+            self.out_port = out_port
+        else:
+            self.out_port = 0
+        if out_group != None:
+            self.out_group = out_group
+        else:
+            self.out_group = 0
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if cookie_mask != None:
+            self.cookie_mask = cookie_mask
+        else:
+            self.cookie_mask = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append('\x00' * 3)
+        packed.append(struct.pack("!L", self.out_port))
+        packed.append(struct.pack("!L", self.out_group))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!Q", self.cookie_mask))
+        packed.append(self.match.pack())
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = aggregate_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_AGGREGATE)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.table_id = reader.read('!B')[0]
+        reader.skip(3)
+        obj.out_port = reader.read('!L')[0]
+        obj.out_group = reader.read('!L')[0]
+        reader.skip(4)
+        obj.cookie = reader.read('!Q')[0]
+        obj.cookie_mask = reader.read('!Q')[0]
+        obj.match = common.match.unpack(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.table_id != other.table_id: return False
+        if self.out_port != other.out_port: return False
+        if self.out_group != other.out_group: return False
+        if self.cookie != other.cookie: return False
+        if self.cookie_mask != other.cookie_mask: return False
+        if self.match != other.match: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("aggregate_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("out_port = ");
+                q.text(util.pretty_port(self.out_port))
+                q.text(","); q.breakable()
+                q.text("out_group = ");
+                q.text("%#x" % self.out_group)
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("cookie_mask = ");
+                q.text("%#x" % self.cookie_mask)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+            q.breakable()
+        q.text('}')
+
+class barrier_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_BARRIER_REPLY
+
+    def __init__(self, xid=None):
+        self.xid = xid
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = barrier_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_BARRIER_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("barrier_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+            q.breakable()
+        q.text('}')
+
+class barrier_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_BARRIER_REQUEST
+
+    def __init__(self, xid=None):
+        self.xid = xid
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = barrier_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_BARRIER_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("barrier_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+            q.breakable()
+        q.text('}')
+
+class bsn_get_interfaces_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_EXPERIMENTER
+    experimenter = 0x5c16c7
+    subtype = 10
+
+    def __init__(self, xid=None, interfaces=None):
+        self.xid = xid
+        if interfaces != None:
+            self.interfaces = interfaces
+        else:
+            self.interfaces = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        packed.append("".join([x.pack() for x in self.interfaces]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = bsn_get_interfaces_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_EXPERIMENTER)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 10)
+        obj.interfaces = loxi.generic_util.unpack_list(reader, common.bsn_interface.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.interfaces != other.interfaces: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_get_interfaces_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("interfaces = ");
+                q.pp(self.interfaces)
+            q.breakable()
+        q.text('}')
+
+class bsn_get_interfaces_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_EXPERIMENTER
+    experimenter = 0x5c16c7
+    subtype = 9
+
+    def __init__(self, xid=None):
+        self.xid = xid
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = bsn_get_interfaces_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_EXPERIMENTER)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 9)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_get_interfaces_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+            q.breakable()
+        q.text('}')
+
+class bsn_get_mirroring_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_EXPERIMENTER
+    experimenter = 0x5c16c7
+    subtype = 5
+
+    def __init__(self, xid=None, report_mirror_ports=None):
+        self.xid = xid
+        if report_mirror_ports != None:
+            self.report_mirror_ports = report_mirror_ports
+        else:
+            self.report_mirror_ports = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        packed.append(struct.pack("!B", self.report_mirror_ports))
+        packed.append('\x00' * 3)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = bsn_get_mirroring_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_EXPERIMENTER)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 5)
+        obj.report_mirror_ports = reader.read('!B')[0]
+        reader.skip(3)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.report_mirror_ports != other.report_mirror_ports: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_get_mirroring_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("report_mirror_ports = ");
+                q.text("%#x" % self.report_mirror_ports)
+            q.breakable()
+        q.text('}')
+
+class bsn_get_mirroring_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_EXPERIMENTER
+    experimenter = 0x5c16c7
+    subtype = 4
+
+    def __init__(self, xid=None, report_mirror_ports=None):
+        self.xid = xid
+        if report_mirror_ports != None:
+            self.report_mirror_ports = report_mirror_ports
+        else:
+            self.report_mirror_ports = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        packed.append(struct.pack("!B", self.report_mirror_ports))
+        packed.append('\x00' * 3)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = bsn_get_mirroring_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_EXPERIMENTER)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 4)
+        obj.report_mirror_ports = reader.read('!B')[0]
+        reader.skip(3)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.report_mirror_ports != other.report_mirror_ports: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_get_mirroring_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("report_mirror_ports = ");
+                q.text("%#x" % self.report_mirror_ports)
+            q.breakable()
+        q.text('}')
+
+class bsn_set_mirroring(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_EXPERIMENTER
+    experimenter = 0x5c16c7
+    subtype = 3
+
+    def __init__(self, xid=None, report_mirror_ports=None):
+        self.xid = xid
+        if report_mirror_ports != None:
+            self.report_mirror_ports = report_mirror_ports
+        else:
+            self.report_mirror_ports = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        packed.append(struct.pack("!B", self.report_mirror_ports))
+        packed.append('\x00' * 3)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = bsn_set_mirroring()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_EXPERIMENTER)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 3)
+        obj.report_mirror_ports = reader.read('!B')[0]
+        reader.skip(3)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.report_mirror_ports != other.report_mirror_ports: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_set_mirroring {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("report_mirror_ports = ");
+                q.text("%#x" % self.report_mirror_ports)
+            q.breakable()
+        q.text('}')
+
+class bsn_set_pktin_suppression(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_EXPERIMENTER
+    experimenter = 0x5c16c7
+    subtype = 11
+
+    def __init__(self, xid=None, enabled=None, idle_timeout=None, hard_timeout=None, priority=None, cookie=None):
+        self.xid = xid
+        if enabled != None:
+            self.enabled = enabled
+        else:
+            self.enabled = 0
+        if idle_timeout != None:
+            self.idle_timeout = idle_timeout
+        else:
+            self.idle_timeout = 0
+        if hard_timeout != None:
+            self.hard_timeout = hard_timeout
+        else:
+            self.hard_timeout = 0
+        if priority != None:
+            self.priority = priority
+        else:
+            self.priority = 0
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        packed.append(struct.pack("!B", self.enabled))
+        packed.append('\x00' * 1)
+        packed.append(struct.pack("!H", self.idle_timeout))
+        packed.append(struct.pack("!H", self.hard_timeout))
+        packed.append(struct.pack("!H", self.priority))
+        packed.append(struct.pack("!Q", self.cookie))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = bsn_set_pktin_suppression()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_EXPERIMENTER)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 11)
+        obj.enabled = reader.read('!B')[0]
+        reader.skip(1)
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.cookie = reader.read('!Q')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.enabled != other.enabled: return False
+        if self.idle_timeout != other.idle_timeout: return False
+        if self.hard_timeout != other.hard_timeout: return False
+        if self.priority != other.priority: return False
+        if self.cookie != other.cookie: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_set_pktin_suppression {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("enabled = ");
+                q.text("%#x" % self.enabled)
+                q.text(","); q.breakable()
+                q.text("idle_timeout = ");
+                q.text("%#x" % self.idle_timeout)
+                q.text(","); q.breakable()
+                q.text("hard_timeout = ");
+                q.text("%#x" % self.hard_timeout)
+                q.text(","); q.breakable()
+                q.text("priority = ");
+                q.text("%#x" % self.priority)
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+            q.breakable()
+        q.text('}')
+
+class desc_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REPLY
+    stats_type = const.OFPST_DESC
+
+    def __init__(self, xid=None, flags=None, mfr_desc=None, hw_desc=None, sw_desc=None, serial_num=None, dp_desc=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if mfr_desc != None:
+            self.mfr_desc = mfr_desc
+        else:
+            self.mfr_desc = ""
+        if hw_desc != None:
+            self.hw_desc = hw_desc
+        else:
+            self.hw_desc = ""
+        if sw_desc != None:
+            self.sw_desc = sw_desc
+        else:
+            self.sw_desc = ""
+        if serial_num != None:
+            self.serial_num = serial_num
+        else:
+            self.serial_num = ""
+        if dp_desc != None:
+            self.dp_desc = dp_desc
+        else:
+            self.dp_desc = ""
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!256s", self.mfr_desc))
+        packed.append(struct.pack("!256s", self.hw_desc))
+        packed.append(struct.pack("!256s", self.sw_desc))
+        packed.append(struct.pack("!32s", self.serial_num))
+        packed.append(struct.pack("!256s", self.dp_desc))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = desc_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_DESC)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.mfr_desc = reader.read("!256s")[0].rstrip("\x00")
+        obj.hw_desc = reader.read("!256s")[0].rstrip("\x00")
+        obj.sw_desc = reader.read("!256s")[0].rstrip("\x00")
+        obj.serial_num = reader.read("!32s")[0].rstrip("\x00")
+        obj.dp_desc = reader.read("!256s")[0].rstrip("\x00")
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.mfr_desc != other.mfr_desc: return False
+        if self.hw_desc != other.hw_desc: return False
+        if self.sw_desc != other.sw_desc: return False
+        if self.serial_num != other.serial_num: return False
+        if self.dp_desc != other.dp_desc: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("desc_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("mfr_desc = ");
+                q.pp(self.mfr_desc)
+                q.text(","); q.breakable()
+                q.text("hw_desc = ");
+                q.pp(self.hw_desc)
+                q.text(","); q.breakable()
+                q.text("sw_desc = ");
+                q.pp(self.sw_desc)
+                q.text(","); q.breakable()
+                q.text("serial_num = ");
+                q.pp(self.serial_num)
+                q.text(","); q.breakable()
+                q.text("dp_desc = ");
+                q.pp(self.dp_desc)
+            q.breakable()
+        q.text('}')
+
+class desc_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REQUEST
+    stats_type = const.OFPST_DESC
+
+    def __init__(self, xid=None, flags=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = desc_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_DESC)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("desc_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+            q.breakable()
+        q.text('}')
+
+class echo_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_ECHO_REPLY
+
+    def __init__(self, xid=None, data=None):
+        self.xid = xid
+        if data != None:
+            self.data = data
+        else:
+            self.data = ""
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(self.data)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = echo_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_ECHO_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.data = str(reader.read_all())
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.data != other.data: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("echo_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("data = ");
+                q.pp(self.data)
+            q.breakable()
+        q.text('}')
+
+class echo_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_ECHO_REQUEST
+
+    def __init__(self, xid=None, data=None):
+        self.xid = xid
+        if data != None:
+            self.data = data
+        else:
+            self.data = ""
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(self.data)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = echo_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_ECHO_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.data = str(reader.read_all())
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.data != other.data: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("echo_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("data = ");
+                q.pp(self.data)
+            q.breakable()
+        q.text('}')
+
+class error_msg(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_ERROR
+
+    def __init__(self, xid=None, err_type=None, code=None, data=None):
+        self.xid = xid
+        if err_type != None:
+            self.err_type = err_type
+        else:
+            self.err_type = 0
+        if code != None:
+            self.code = code
+        else:
+            self.code = 0
+        if data != None:
+            self.data = data
+        else:
+            self.data = ""
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.err_type))
+        packed.append(struct.pack("!H", self.code))
+        packed.append(self.data)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = error_msg()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_ERROR)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.err_type = reader.read('!H')[0]
+        obj.code = reader.read('!H')[0]
+        obj.data = str(reader.read_all())
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.err_type != other.err_type: return False
+        if self.code != other.code: return False
+        if self.data != other.data: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("error_msg {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("err_type = ");
+                q.text("%#x" % self.err_type)
+                q.text(","); q.breakable()
+                q.text("code = ");
+                q.text("%#x" % self.code)
+                q.text(","); q.breakable()
+                q.text("data = ");
+                q.pp(self.data)
+            q.breakable()
+        q.text('}')
+
+class experimenter_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REPLY
+    stats_type = const.OFPST_EXPERIMENTER
+
+    def __init__(self, xid=None, flags=None, experimenter=None, data=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if experimenter != None:
+            self.experimenter = experimenter
+        else:
+            self.experimenter = 0
+        if data != None:
+            self.data = data
+        else:
+            self.data = ""
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append('\x00' * 4)
+        packed.append(self.data)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = experimenter_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_EXPERIMENTER)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.experimenter = reader.read('!L')[0]
+        reader.skip(4)
+        obj.data = str(reader.read_all())
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.experimenter != other.experimenter: return False
+        if self.data != other.data: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("experimenter_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("experimenter = ");
+                q.text("%#x" % self.experimenter)
+                q.text(","); q.breakable()
+                q.text("data = ");
+                q.pp(self.data)
+            q.breakable()
+        q.text('}')
+
+class experimenter_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REQUEST
+    stats_type = const.OFPST_EXPERIMENTER
+
+    def __init__(self, xid=None, flags=None, experimenter=None, data=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if experimenter != None:
+            self.experimenter = experimenter
+        else:
+            self.experimenter = 0
+        if data != None:
+            self.data = data
+        else:
+            self.data = ""
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append('\x00' * 4)
+        packed.append(self.data)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = experimenter_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_EXPERIMENTER)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.experimenter = reader.read('!L')[0]
+        reader.skip(4)
+        obj.data = str(reader.read_all())
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.experimenter != other.experimenter: return False
+        if self.data != other.data: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("experimenter_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("experimenter = ");
+                q.text("%#x" % self.experimenter)
+                q.text(","); q.breakable()
+                q.text("data = ");
+                q.pp(self.data)
+            q.breakable()
+        q.text('}')
+
+class features_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_FEATURES_REPLY
+
+    def __init__(self, xid=None, datapath_id=None, n_buffers=None, n_tables=None, capabilities=None, reserved=None, ports=None):
+        self.xid = xid
+        if datapath_id != None:
+            self.datapath_id = datapath_id
+        else:
+            self.datapath_id = 0
+        if n_buffers != None:
+            self.n_buffers = n_buffers
+        else:
+            self.n_buffers = 0
+        if n_tables != None:
+            self.n_tables = n_tables
+        else:
+            self.n_tables = 0
+        if capabilities != None:
+            self.capabilities = capabilities
+        else:
+            self.capabilities = 0
+        if reserved != None:
+            self.reserved = reserved
+        else:
+            self.reserved = 0
+        if ports != None:
+            self.ports = ports
+        else:
+            self.ports = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!Q", self.datapath_id))
+        packed.append(struct.pack("!L", self.n_buffers))
+        packed.append(struct.pack("!B", self.n_tables))
+        packed.append('\x00' * 3)
+        packed.append(struct.pack("!L", self.capabilities))
+        packed.append(struct.pack("!L", self.reserved))
+        packed.append("".join([x.pack() for x in self.ports]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = features_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FEATURES_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.datapath_id = reader.read('!Q')[0]
+        obj.n_buffers = reader.read('!L')[0]
+        obj.n_tables = reader.read('!B')[0]
+        reader.skip(3)
+        obj.capabilities = reader.read('!L')[0]
+        obj.reserved = reader.read('!L')[0]
+        obj.ports = loxi.generic_util.unpack_list(reader, common.port_desc.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.datapath_id != other.datapath_id: return False
+        if self.n_buffers != other.n_buffers: return False
+        if self.n_tables != other.n_tables: return False
+        if self.capabilities != other.capabilities: return False
+        if self.reserved != other.reserved: return False
+        if self.ports != other.ports: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("features_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("datapath_id = ");
+                q.text("%#x" % self.datapath_id)
+                q.text(","); q.breakable()
+                q.text("n_buffers = ");
+                q.text("%#x" % self.n_buffers)
+                q.text(","); q.breakable()
+                q.text("n_tables = ");
+                q.text("%#x" % self.n_tables)
+                q.text(","); q.breakable()
+                q.text("capabilities = ");
+                q.text("%#x" % self.capabilities)
+                q.text(","); q.breakable()
+                q.text("reserved = ");
+                q.text("%#x" % self.reserved)
+                q.text(","); q.breakable()
+                q.text("ports = ");
+                q.pp(self.ports)
+            q.breakable()
+        q.text('}')
+
+class features_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_FEATURES_REQUEST
+
+    def __init__(self, xid=None):
+        self.xid = xid
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = features_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FEATURES_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("features_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+            q.breakable()
+        q.text('}')
+
+class flow_add(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_FLOW_MOD
+    _command = const.OFPFC_ADD
+
+    def __init__(self, xid=None, cookie=None, cookie_mask=None, table_id=None, idle_timeout=None, hard_timeout=None, priority=None, buffer_id=None, out_port=None, out_group=None, flags=None, match=None, instructions=None):
+        self.xid = xid
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if cookie_mask != None:
+            self.cookie_mask = cookie_mask
+        else:
+            self.cookie_mask = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if idle_timeout != None:
+            self.idle_timeout = idle_timeout
+        else:
+            self.idle_timeout = 0
+        if hard_timeout != None:
+            self.hard_timeout = hard_timeout
+        else:
+            self.hard_timeout = 0
+        if priority != None:
+            self.priority = priority
+        else:
+            self.priority = 0
+        if buffer_id != None:
+            self.buffer_id = buffer_id
+        else:
+            self.buffer_id = 0
+        if out_port != None:
+            self.out_port = out_port
+        else:
+            self.out_port = 0
+        if out_group != None:
+            self.out_group = out_group
+        else:
+            self.out_group = 0
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+        if instructions != None:
+            self.instructions = instructions
+        else:
+            self.instructions = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!Q", self.cookie_mask))
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append(struct.pack("!B", self._command))
+        packed.append(struct.pack("!H", self.idle_timeout))
+        packed.append(struct.pack("!H", self.hard_timeout))
+        packed.append(struct.pack("!H", self.priority))
+        packed.append(struct.pack("!L", self.buffer_id))
+        packed.append(struct.pack("!L", self.out_port))
+        packed.append(struct.pack("!L", self.out_group))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 2)
+        packed.append(self.match.pack())
+        packed.append("".join([x.pack() for x in self.instructions]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = flow_add()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FLOW_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.cookie = reader.read('!Q')[0]
+        obj.cookie_mask = reader.read('!Q')[0]
+        obj.table_id = reader.read('!B')[0]
+        __command = reader.read('!B')[0]
+        assert(__command == const.OFPFC_ADD)
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.out_port = reader.read('!L')[0]
+        obj.out_group = reader.read('!L')[0]
+        obj.flags = reader.read('!H')[0]
+        reader.skip(2)
+        obj.match = common.match.unpack(reader)
+        obj.instructions = instruction.unpack_list(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.cookie != other.cookie: return False
+        if self.cookie_mask != other.cookie_mask: return False
+        if self.table_id != other.table_id: return False
+        if self.idle_timeout != other.idle_timeout: return False
+        if self.hard_timeout != other.hard_timeout: return False
+        if self.priority != other.priority: return False
+        if self.buffer_id != other.buffer_id: return False
+        if self.out_port != other.out_port: return False
+        if self.out_group != other.out_group: return False
+        if self.flags != other.flags: return False
+        if self.match != other.match: return False
+        if self.instructions != other.instructions: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_add {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("cookie_mask = ");
+                q.text("%#x" % self.cookie_mask)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("idle_timeout = ");
+                q.text("%#x" % self.idle_timeout)
+                q.text(","); q.breakable()
+                q.text("hard_timeout = ");
+                q.text("%#x" % self.hard_timeout)
+                q.text(","); q.breakable()
+                q.text("priority = ");
+                q.text("%#x" % self.priority)
+                q.text(","); q.breakable()
+                q.text("buffer_id = ");
+                q.text("%#x" % self.buffer_id)
+                q.text(","); q.breakable()
+                q.text("out_port = ");
+                q.text(util.pretty_port(self.out_port))
+                q.text(","); q.breakable()
+                q.text("out_group = ");
+                q.text("%#x" % self.out_group)
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+                q.text(","); q.breakable()
+                q.text("instructions = ");
+                q.pp(self.instructions)
+            q.breakable()
+        q.text('}')
+
+class flow_delete(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_FLOW_MOD
+    _command = const.OFPFC_DELETE
+
+    def __init__(self, xid=None, cookie=None, cookie_mask=None, table_id=None, idle_timeout=None, hard_timeout=None, priority=None, buffer_id=None, out_port=None, out_group=None, flags=None, match=None, instructions=None):
+        self.xid = xid
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if cookie_mask != None:
+            self.cookie_mask = cookie_mask
+        else:
+            self.cookie_mask = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if idle_timeout != None:
+            self.idle_timeout = idle_timeout
+        else:
+            self.idle_timeout = 0
+        if hard_timeout != None:
+            self.hard_timeout = hard_timeout
+        else:
+            self.hard_timeout = 0
+        if priority != None:
+            self.priority = priority
+        else:
+            self.priority = 0
+        if buffer_id != None:
+            self.buffer_id = buffer_id
+        else:
+            self.buffer_id = 0
+        if out_port != None:
+            self.out_port = out_port
+        else:
+            self.out_port = 0
+        if out_group != None:
+            self.out_group = out_group
+        else:
+            self.out_group = 0
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+        if instructions != None:
+            self.instructions = instructions
+        else:
+            self.instructions = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!Q", self.cookie_mask))
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append(struct.pack("!B", self._command))
+        packed.append(struct.pack("!H", self.idle_timeout))
+        packed.append(struct.pack("!H", self.hard_timeout))
+        packed.append(struct.pack("!H", self.priority))
+        packed.append(struct.pack("!L", self.buffer_id))
+        packed.append(struct.pack("!L", self.out_port))
+        packed.append(struct.pack("!L", self.out_group))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 2)
+        packed.append(self.match.pack())
+        packed.append("".join([x.pack() for x in self.instructions]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = flow_delete()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FLOW_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.cookie = reader.read('!Q')[0]
+        obj.cookie_mask = reader.read('!Q')[0]
+        obj.table_id = reader.read('!B')[0]
+        __command = reader.read('!B')[0]
+        assert(__command == const.OFPFC_DELETE)
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.out_port = reader.read('!L')[0]
+        obj.out_group = reader.read('!L')[0]
+        obj.flags = reader.read('!H')[0]
+        reader.skip(2)
+        obj.match = common.match.unpack(reader)
+        obj.instructions = instruction.unpack_list(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.cookie != other.cookie: return False
+        if self.cookie_mask != other.cookie_mask: return False
+        if self.table_id != other.table_id: return False
+        if self.idle_timeout != other.idle_timeout: return False
+        if self.hard_timeout != other.hard_timeout: return False
+        if self.priority != other.priority: return False
+        if self.buffer_id != other.buffer_id: return False
+        if self.out_port != other.out_port: return False
+        if self.out_group != other.out_group: return False
+        if self.flags != other.flags: return False
+        if self.match != other.match: return False
+        if self.instructions != other.instructions: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_delete {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("cookie_mask = ");
+                q.text("%#x" % self.cookie_mask)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("idle_timeout = ");
+                q.text("%#x" % self.idle_timeout)
+                q.text(","); q.breakable()
+                q.text("hard_timeout = ");
+                q.text("%#x" % self.hard_timeout)
+                q.text(","); q.breakable()
+                q.text("priority = ");
+                q.text("%#x" % self.priority)
+                q.text(","); q.breakable()
+                q.text("buffer_id = ");
+                q.text("%#x" % self.buffer_id)
+                q.text(","); q.breakable()
+                q.text("out_port = ");
+                q.text(util.pretty_port(self.out_port))
+                q.text(","); q.breakable()
+                q.text("out_group = ");
+                q.text("%#x" % self.out_group)
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+                q.text(","); q.breakable()
+                q.text("instructions = ");
+                q.pp(self.instructions)
+            q.breakable()
+        q.text('}')
+
+class flow_delete_strict(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_FLOW_MOD
+    _command = const.OFPFC_DELETE_STRICT
+
+    def __init__(self, xid=None, cookie=None, cookie_mask=None, table_id=None, idle_timeout=None, hard_timeout=None, priority=None, buffer_id=None, out_port=None, out_group=None, flags=None, match=None, instructions=None):
+        self.xid = xid
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if cookie_mask != None:
+            self.cookie_mask = cookie_mask
+        else:
+            self.cookie_mask = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if idle_timeout != None:
+            self.idle_timeout = idle_timeout
+        else:
+            self.idle_timeout = 0
+        if hard_timeout != None:
+            self.hard_timeout = hard_timeout
+        else:
+            self.hard_timeout = 0
+        if priority != None:
+            self.priority = priority
+        else:
+            self.priority = 0
+        if buffer_id != None:
+            self.buffer_id = buffer_id
+        else:
+            self.buffer_id = 0
+        if out_port != None:
+            self.out_port = out_port
+        else:
+            self.out_port = 0
+        if out_group != None:
+            self.out_group = out_group
+        else:
+            self.out_group = 0
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+        if instructions != None:
+            self.instructions = instructions
+        else:
+            self.instructions = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!Q", self.cookie_mask))
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append(struct.pack("!B", self._command))
+        packed.append(struct.pack("!H", self.idle_timeout))
+        packed.append(struct.pack("!H", self.hard_timeout))
+        packed.append(struct.pack("!H", self.priority))
+        packed.append(struct.pack("!L", self.buffer_id))
+        packed.append(struct.pack("!L", self.out_port))
+        packed.append(struct.pack("!L", self.out_group))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 2)
+        packed.append(self.match.pack())
+        packed.append("".join([x.pack() for x in self.instructions]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = flow_delete_strict()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FLOW_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.cookie = reader.read('!Q')[0]
+        obj.cookie_mask = reader.read('!Q')[0]
+        obj.table_id = reader.read('!B')[0]
+        __command = reader.read('!B')[0]
+        assert(__command == const.OFPFC_DELETE_STRICT)
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.out_port = reader.read('!L')[0]
+        obj.out_group = reader.read('!L')[0]
+        obj.flags = reader.read('!H')[0]
+        reader.skip(2)
+        obj.match = common.match.unpack(reader)
+        obj.instructions = instruction.unpack_list(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.cookie != other.cookie: return False
+        if self.cookie_mask != other.cookie_mask: return False
+        if self.table_id != other.table_id: return False
+        if self.idle_timeout != other.idle_timeout: return False
+        if self.hard_timeout != other.hard_timeout: return False
+        if self.priority != other.priority: return False
+        if self.buffer_id != other.buffer_id: return False
+        if self.out_port != other.out_port: return False
+        if self.out_group != other.out_group: return False
+        if self.flags != other.flags: return False
+        if self.match != other.match: return False
+        if self.instructions != other.instructions: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_delete_strict {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("cookie_mask = ");
+                q.text("%#x" % self.cookie_mask)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("idle_timeout = ");
+                q.text("%#x" % self.idle_timeout)
+                q.text(","); q.breakable()
+                q.text("hard_timeout = ");
+                q.text("%#x" % self.hard_timeout)
+                q.text(","); q.breakable()
+                q.text("priority = ");
+                q.text("%#x" % self.priority)
+                q.text(","); q.breakable()
+                q.text("buffer_id = ");
+                q.text("%#x" % self.buffer_id)
+                q.text(","); q.breakable()
+                q.text("out_port = ");
+                q.text(util.pretty_port(self.out_port))
+                q.text(","); q.breakable()
+                q.text("out_group = ");
+                q.text("%#x" % self.out_group)
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+                q.text(","); q.breakable()
+                q.text("instructions = ");
+                q.pp(self.instructions)
+            q.breakable()
+        q.text('}')
+
+class flow_modify(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_FLOW_MOD
+    _command = const.OFPFC_MODIFY
+
+    def __init__(self, xid=None, cookie=None, cookie_mask=None, table_id=None, idle_timeout=None, hard_timeout=None, priority=None, buffer_id=None, out_port=None, out_group=None, flags=None, match=None, instructions=None):
+        self.xid = xid
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if cookie_mask != None:
+            self.cookie_mask = cookie_mask
+        else:
+            self.cookie_mask = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if idle_timeout != None:
+            self.idle_timeout = idle_timeout
+        else:
+            self.idle_timeout = 0
+        if hard_timeout != None:
+            self.hard_timeout = hard_timeout
+        else:
+            self.hard_timeout = 0
+        if priority != None:
+            self.priority = priority
+        else:
+            self.priority = 0
+        if buffer_id != None:
+            self.buffer_id = buffer_id
+        else:
+            self.buffer_id = 0
+        if out_port != None:
+            self.out_port = out_port
+        else:
+            self.out_port = 0
+        if out_group != None:
+            self.out_group = out_group
+        else:
+            self.out_group = 0
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+        if instructions != None:
+            self.instructions = instructions
+        else:
+            self.instructions = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!Q", self.cookie_mask))
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append(struct.pack("!B", self._command))
+        packed.append(struct.pack("!H", self.idle_timeout))
+        packed.append(struct.pack("!H", self.hard_timeout))
+        packed.append(struct.pack("!H", self.priority))
+        packed.append(struct.pack("!L", self.buffer_id))
+        packed.append(struct.pack("!L", self.out_port))
+        packed.append(struct.pack("!L", self.out_group))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 2)
+        packed.append(self.match.pack())
+        packed.append("".join([x.pack() for x in self.instructions]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = flow_modify()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FLOW_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.cookie = reader.read('!Q')[0]
+        obj.cookie_mask = reader.read('!Q')[0]
+        obj.table_id = reader.read('!B')[0]
+        __command = reader.read('!B')[0]
+        assert(__command == const.OFPFC_MODIFY)
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.out_port = reader.read('!L')[0]
+        obj.out_group = reader.read('!L')[0]
+        obj.flags = reader.read('!H')[0]
+        reader.skip(2)
+        obj.match = common.match.unpack(reader)
+        obj.instructions = instruction.unpack_list(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.cookie != other.cookie: return False
+        if self.cookie_mask != other.cookie_mask: return False
+        if self.table_id != other.table_id: return False
+        if self.idle_timeout != other.idle_timeout: return False
+        if self.hard_timeout != other.hard_timeout: return False
+        if self.priority != other.priority: return False
+        if self.buffer_id != other.buffer_id: return False
+        if self.out_port != other.out_port: return False
+        if self.out_group != other.out_group: return False
+        if self.flags != other.flags: return False
+        if self.match != other.match: return False
+        if self.instructions != other.instructions: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_modify {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("cookie_mask = ");
+                q.text("%#x" % self.cookie_mask)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("idle_timeout = ");
+                q.text("%#x" % self.idle_timeout)
+                q.text(","); q.breakable()
+                q.text("hard_timeout = ");
+                q.text("%#x" % self.hard_timeout)
+                q.text(","); q.breakable()
+                q.text("priority = ");
+                q.text("%#x" % self.priority)
+                q.text(","); q.breakable()
+                q.text("buffer_id = ");
+                q.text("%#x" % self.buffer_id)
+                q.text(","); q.breakable()
+                q.text("out_port = ");
+                q.text(util.pretty_port(self.out_port))
+                q.text(","); q.breakable()
+                q.text("out_group = ");
+                q.text("%#x" % self.out_group)
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+                q.text(","); q.breakable()
+                q.text("instructions = ");
+                q.pp(self.instructions)
+            q.breakable()
+        q.text('}')
+
+class flow_modify_strict(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_FLOW_MOD
+    _command = const.OFPFC_MODIFY_STRICT
+
+    def __init__(self, xid=None, cookie=None, cookie_mask=None, table_id=None, idle_timeout=None, hard_timeout=None, priority=None, buffer_id=None, out_port=None, out_group=None, flags=None, match=None, instructions=None):
+        self.xid = xid
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if cookie_mask != None:
+            self.cookie_mask = cookie_mask
+        else:
+            self.cookie_mask = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if idle_timeout != None:
+            self.idle_timeout = idle_timeout
+        else:
+            self.idle_timeout = 0
+        if hard_timeout != None:
+            self.hard_timeout = hard_timeout
+        else:
+            self.hard_timeout = 0
+        if priority != None:
+            self.priority = priority
+        else:
+            self.priority = 0
+        if buffer_id != None:
+            self.buffer_id = buffer_id
+        else:
+            self.buffer_id = 0
+        if out_port != None:
+            self.out_port = out_port
+        else:
+            self.out_port = 0
+        if out_group != None:
+            self.out_group = out_group
+        else:
+            self.out_group = 0
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+        if instructions != None:
+            self.instructions = instructions
+        else:
+            self.instructions = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!Q", self.cookie_mask))
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append(struct.pack("!B", self._command))
+        packed.append(struct.pack("!H", self.idle_timeout))
+        packed.append(struct.pack("!H", self.hard_timeout))
+        packed.append(struct.pack("!H", self.priority))
+        packed.append(struct.pack("!L", self.buffer_id))
+        packed.append(struct.pack("!L", self.out_port))
+        packed.append(struct.pack("!L", self.out_group))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 2)
+        packed.append(self.match.pack())
+        packed.append("".join([x.pack() for x in self.instructions]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = flow_modify_strict()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FLOW_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.cookie = reader.read('!Q')[0]
+        obj.cookie_mask = reader.read('!Q')[0]
+        obj.table_id = reader.read('!B')[0]
+        __command = reader.read('!B')[0]
+        assert(__command == const.OFPFC_MODIFY_STRICT)
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.out_port = reader.read('!L')[0]
+        obj.out_group = reader.read('!L')[0]
+        obj.flags = reader.read('!H')[0]
+        reader.skip(2)
+        obj.match = common.match.unpack(reader)
+        obj.instructions = instruction.unpack_list(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.cookie != other.cookie: return False
+        if self.cookie_mask != other.cookie_mask: return False
+        if self.table_id != other.table_id: return False
+        if self.idle_timeout != other.idle_timeout: return False
+        if self.hard_timeout != other.hard_timeout: return False
+        if self.priority != other.priority: return False
+        if self.buffer_id != other.buffer_id: return False
+        if self.out_port != other.out_port: return False
+        if self.out_group != other.out_group: return False
+        if self.flags != other.flags: return False
+        if self.match != other.match: return False
+        if self.instructions != other.instructions: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_modify_strict {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("cookie_mask = ");
+                q.text("%#x" % self.cookie_mask)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("idle_timeout = ");
+                q.text("%#x" % self.idle_timeout)
+                q.text(","); q.breakable()
+                q.text("hard_timeout = ");
+                q.text("%#x" % self.hard_timeout)
+                q.text(","); q.breakable()
+                q.text("priority = ");
+                q.text("%#x" % self.priority)
+                q.text(","); q.breakable()
+                q.text("buffer_id = ");
+                q.text("%#x" % self.buffer_id)
+                q.text(","); q.breakable()
+                q.text("out_port = ");
+                q.text(util.pretty_port(self.out_port))
+                q.text(","); q.breakable()
+                q.text("out_group = ");
+                q.text("%#x" % self.out_group)
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+                q.text(","); q.breakable()
+                q.text("instructions = ");
+                q.pp(self.instructions)
+            q.breakable()
+        q.text('}')
+
+class flow_removed(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_FLOW_REMOVED
+
+    def __init__(self, xid=None, cookie=None, priority=None, reason=None, table_id=None, duration_sec=None, duration_nsec=None, idle_timeout=None, packet_count=None, byte_count=None, match=None):
+        self.xid = xid
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if priority != None:
+            self.priority = priority
+        else:
+            self.priority = 0
+        if reason != None:
+            self.reason = reason
+        else:
+            self.reason = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if duration_sec != None:
+            self.duration_sec = duration_sec
+        else:
+            self.duration_sec = 0
+        if duration_nsec != None:
+            self.duration_nsec = duration_nsec
+        else:
+            self.duration_nsec = 0
+        if idle_timeout != None:
+            self.idle_timeout = idle_timeout
+        else:
+            self.idle_timeout = 0
+        if packet_count != None:
+            self.packet_count = packet_count
+        else:
+            self.packet_count = 0
+        if byte_count != None:
+            self.byte_count = byte_count
+        else:
+            self.byte_count = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!H", self.priority))
+        packed.append(struct.pack("!B", self.reason))
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append(struct.pack("!L", self.duration_sec))
+        packed.append(struct.pack("!L", self.duration_nsec))
+        packed.append(struct.pack("!H", self.idle_timeout))
+        packed.append('\x00' * 2)
+        packed.append(struct.pack("!Q", self.packet_count))
+        packed.append(struct.pack("!Q", self.byte_count))
+        packed.append(self.match.pack())
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = flow_removed()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FLOW_REMOVED)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.cookie = reader.read('!Q')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.reason = reader.read('!B')[0]
+        obj.table_id = reader.read('!B')[0]
+        obj.duration_sec = reader.read('!L')[0]
+        obj.duration_nsec = reader.read('!L')[0]
+        obj.idle_timeout = reader.read('!H')[0]
+        reader.skip(2)
+        obj.packet_count = reader.read('!Q')[0]
+        obj.byte_count = reader.read('!Q')[0]
+        obj.match = common.match.unpack(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.cookie != other.cookie: return False
+        if self.priority != other.priority: return False
+        if self.reason != other.reason: return False
+        if self.table_id != other.table_id: return False
+        if self.duration_sec != other.duration_sec: return False
+        if self.duration_nsec != other.duration_nsec: return False
+        if self.idle_timeout != other.idle_timeout: return False
+        if self.packet_count != other.packet_count: return False
+        if self.byte_count != other.byte_count: return False
+        if self.match != other.match: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_removed {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("priority = ");
+                q.text("%#x" % self.priority)
+                q.text(","); q.breakable()
+                q.text("reason = ");
+                q.text("%#x" % self.reason)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("duration_sec = ");
+                q.text("%#x" % self.duration_sec)
+                q.text(","); q.breakable()
+                q.text("duration_nsec = ");
+                q.text("%#x" % self.duration_nsec)
+                q.text(","); q.breakable()
+                q.text("idle_timeout = ");
+                q.text("%#x" % self.idle_timeout)
+                q.text(","); q.breakable()
+                q.text("packet_count = ");
+                q.text("%#x" % self.packet_count)
+                q.text(","); q.breakable()
+                q.text("byte_count = ");
+                q.text("%#x" % self.byte_count)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+            q.breakable()
+        q.text('}')
+
+class flow_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REPLY
+    stats_type = const.OFPST_FLOW
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.entries]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = flow_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_FLOW)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.entries = common.unpack_list_flow_stats_entry(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.entries != other.entries: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("entries = ");
+                q.pp(self.entries)
+            q.breakable()
+        q.text('}')
+
+class flow_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REQUEST
+    stats_type = const.OFPST_FLOW
+
+    def __init__(self, xid=None, flags=None, table_id=None, out_port=None, out_group=None, cookie=None, cookie_mask=None, match=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if out_port != None:
+            self.out_port = out_port
+        else:
+            self.out_port = 0
+        if out_group != None:
+            self.out_group = out_group
+        else:
+            self.out_group = 0
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if cookie_mask != None:
+            self.cookie_mask = cookie_mask
+        else:
+            self.cookie_mask = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append('\x00' * 3)
+        packed.append(struct.pack("!L", self.out_port))
+        packed.append(struct.pack("!L", self.out_group))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!Q", self.cookie_mask))
+        packed.append(self.match.pack())
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = flow_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_FLOW)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.table_id = reader.read('!B')[0]
+        reader.skip(3)
+        obj.out_port = reader.read('!L')[0]
+        obj.out_group = reader.read('!L')[0]
+        reader.skip(4)
+        obj.cookie = reader.read('!Q')[0]
+        obj.cookie_mask = reader.read('!Q')[0]
+        obj.match = common.match.unpack(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.table_id != other.table_id: return False
+        if self.out_port != other.out_port: return False
+        if self.out_group != other.out_group: return False
+        if self.cookie != other.cookie: return False
+        if self.cookie_mask != other.cookie_mask: return False
+        if self.match != other.match: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("out_port = ");
+                q.text(util.pretty_port(self.out_port))
+                q.text(","); q.breakable()
+                q.text("out_group = ");
+                q.text("%#x" % self.out_group)
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("cookie_mask = ");
+                q.text("%#x" % self.cookie_mask)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+            q.breakable()
+        q.text('}')
+
+class get_config_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_GET_CONFIG_REPLY
+
+    def __init__(self, xid=None, flags=None, miss_send_len=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if miss_send_len != None:
+            self.miss_send_len = miss_send_len
+        else:
+            self.miss_send_len = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append(struct.pack("!H", self.miss_send_len))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = get_config_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_GET_CONFIG_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.flags = reader.read('!H')[0]
+        obj.miss_send_len = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.miss_send_len != other.miss_send_len: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("get_config_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("miss_send_len = ");
+                q.text("%#x" % self.miss_send_len)
+            q.breakable()
+        q.text('}')
+
+class get_config_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_GET_CONFIG_REQUEST
+
+    def __init__(self, xid=None):
+        self.xid = xid
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = get_config_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_GET_CONFIG_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("get_config_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+            q.breakable()
+        q.text('}')
+
+class group_desc_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REPLY
+    stats_type = const.OFPST_GROUP_DESC
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.entries]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = group_desc_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_GROUP_DESC)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.entries = common.unpack_list_group_desc_stats_entry(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.entries != other.entries: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group_desc_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("entries = ");
+                q.pp(self.entries)
+            q.breakable()
+        q.text('}')
+
+class group_desc_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REQUEST
+    stats_type = const.OFPST_GROUP_DESC
+
+    def __init__(self, xid=None, flags=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = group_desc_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_GROUP_DESC)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group_desc_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+            q.breakable()
+        q.text('}')
+
+class group_mod(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_GROUP_MOD
+
+    def __init__(self, xid=None, command=None, group_type=None, group_id=None, buckets=None):
+        self.xid = xid
+        if command != None:
+            self.command = command
+        else:
+            self.command = 0
+        if group_type != None:
+            self.group_type = group_type
+        else:
+            self.group_type = 0
+        if group_id != None:
+            self.group_id = group_id
+        else:
+            self.group_id = 0
+        if buckets != None:
+            self.buckets = buckets
+        else:
+            self.buckets = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.command))
+        packed.append(struct.pack("!B", self.group_type))
+        packed.append('\x00' * 1)
+        packed.append(struct.pack("!L", self.group_id))
+        packed.append("".join([x.pack() for x in self.buckets]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = group_mod()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_GROUP_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.command = reader.read('!H')[0]
+        obj.group_type = reader.read('!B')[0]
+        reader.skip(1)
+        obj.group_id = reader.read('!L')[0]
+        obj.buckets = common.unpack_list_bucket(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.command != other.command: return False
+        if self.group_type != other.group_type: return False
+        if self.group_id != other.group_id: return False
+        if self.buckets != other.buckets: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group_mod {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("command = ");
+                q.text("%#x" % self.command)
+                q.text(","); q.breakable()
+                q.text("group_type = ");
+                q.text("%#x" % self.group_type)
+                q.text(","); q.breakable()
+                q.text("group_id = ");
+                q.text("%#x" % self.group_id)
+                q.text(","); q.breakable()
+                q.text("buckets = ");
+                q.pp(self.buckets)
+            q.breakable()
+        q.text('}')
+
+class group_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REPLY
+    stats_type = const.OFPST_GROUP
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.entries]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = group_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_GROUP)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.entries = common.unpack_list_group_stats_entry(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.entries != other.entries: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("entries = ");
+                q.pp(self.entries)
+            q.breakable()
+        q.text('}')
+
+class group_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REQUEST
+    stats_type = const.OFPST_GROUP
+
+    def __init__(self, xid=None, flags=None, group_id=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if group_id != None:
+            self.group_id = group_id
+        else:
+            self.group_id = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!L", self.group_id))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = group_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_GROUP)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.group_id = reader.read('!L')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.group_id != other.group_id: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("group_id = ");
+                q.text("%#x" % self.group_id)
+            q.breakable()
+        q.text('}')
+
+class hello(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_HELLO
+
+    def __init__(self, xid=None):
+        self.xid = xid
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = hello()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_HELLO)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("hello {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+            q.breakable()
+        q.text('}')
+
+class packet_in(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_PACKET_IN
+
+    def __init__(self, xid=None, buffer_id=None, in_port=None, in_phy_port=None, total_len=None, reason=None, table_id=None, data=None):
+        self.xid = xid
+        if buffer_id != None:
+            self.buffer_id = buffer_id
+        else:
+            self.buffer_id = 0
+        if in_port != None:
+            self.in_port = in_port
+        else:
+            self.in_port = 0
+        if in_phy_port != None:
+            self.in_phy_port = in_phy_port
+        else:
+            self.in_phy_port = 0
+        if total_len != None:
+            self.total_len = total_len
+        else:
+            self.total_len = 0
+        if reason != None:
+            self.reason = reason
+        else:
+            self.reason = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if data != None:
+            self.data = data
+        else:
+            self.data = ""
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.buffer_id))
+        packed.append(struct.pack("!L", self.in_port))
+        packed.append(struct.pack("!L", self.in_phy_port))
+        packed.append(struct.pack("!H", self.total_len))
+        packed.append(struct.pack("!B", self.reason))
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append(self.data)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = packet_in()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_PACKET_IN)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.in_port = reader.read('!L')[0]
+        obj.in_phy_port = reader.read('!L')[0]
+        obj.total_len = reader.read('!H')[0]
+        obj.reason = reader.read('!B')[0]
+        obj.table_id = reader.read('!B')[0]
+        obj.data = str(reader.read_all())
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.buffer_id != other.buffer_id: return False
+        if self.in_port != other.in_port: return False
+        if self.in_phy_port != other.in_phy_port: return False
+        if self.total_len != other.total_len: return False
+        if self.reason != other.reason: return False
+        if self.table_id != other.table_id: return False
+        if self.data != other.data: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("packet_in {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("buffer_id = ");
+                q.text("%#x" % self.buffer_id)
+                q.text(","); q.breakable()
+                q.text("in_port = ");
+                q.text(util.pretty_port(self.in_port))
+                q.text(","); q.breakable()
+                q.text("in_phy_port = ");
+                q.text(util.pretty_port(self.in_phy_port))
+                q.text(","); q.breakable()
+                q.text("total_len = ");
+                q.text("%#x" % self.total_len)
+                q.text(","); q.breakable()
+                q.text("reason = ");
+                q.text("%#x" % self.reason)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("data = ");
+                q.pp(self.data)
+            q.breakable()
+        q.text('}')
+
+class packet_out(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_PACKET_OUT
+
+    def __init__(self, xid=None, buffer_id=None, in_port=None, actions=None, data=None):
+        self.xid = xid
+        if buffer_id != None:
+            self.buffer_id = buffer_id
+        else:
+            self.buffer_id = 0
+        if in_port != None:
+            self.in_port = in_port
+        else:
+            self.in_port = 0
+        if actions != None:
+            self.actions = actions
+        else:
+            self.actions = []
+        if data != None:
+            self.data = data
+        else:
+            self.data = ""
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.buffer_id))
+        packed.append(struct.pack("!L", self.in_port))
+        packed.append(struct.pack("!H", 0)) # placeholder for actions_len at index 6
+        packed.append('\x00' * 6)
+        packed.append("".join([x.pack() for x in self.actions]))
+        packed[6] = struct.pack("!H", len(packed[-1]))
+        packed.append(self.data)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = packet_out()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_PACKET_OUT)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.in_port = reader.read('!L')[0]
+        _actions_len = reader.read('!H')[0]
+        reader.skip(6)
+        obj.actions = action.unpack_list(reader.slice(_actions_len))
+        obj.data = str(reader.read_all())
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.buffer_id != other.buffer_id: return False
+        if self.in_port != other.in_port: return False
+        if self.actions != other.actions: return False
+        if self.data != other.data: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("packet_out {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("buffer_id = ");
+                q.text("%#x" % self.buffer_id)
+                q.text(","); q.breakable()
+                q.text("in_port = ");
+                q.text(util.pretty_port(self.in_port))
+                q.text(","); q.breakable()
+                q.text("actions = ");
+                q.pp(self.actions)
+                q.text(","); q.breakable()
+                q.text("data = ");
+                q.pp(self.data)
+            q.breakable()
+        q.text('}')
+
+class port_mod(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_PORT_MOD
+
+    def __init__(self, xid=None, port_no=None, hw_addr=None, config=None, mask=None, advertise=None):
+        self.xid = xid
+        if port_no != None:
+            self.port_no = port_no
+        else:
+            self.port_no = 0
+        if hw_addr != None:
+            self.hw_addr = hw_addr
+        else:
+            self.hw_addr = [0,0,0,0,0,0]
+        if config != None:
+            self.config = config
+        else:
+            self.config = 0
+        if mask != None:
+            self.mask = mask
+        else:
+            self.mask = 0
+        if advertise != None:
+            self.advertise = advertise
+        else:
+            self.advertise = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.port_no))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!6B", *self.hw_addr))
+        packed.append('\x00' * 2)
+        packed.append(struct.pack("!L", self.config))
+        packed.append(struct.pack("!L", self.mask))
+        packed.append(struct.pack("!L", self.advertise))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = port_mod()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_PORT_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.port_no = reader.read('!L')[0]
+        reader.skip(4)
+        obj.hw_addr = list(reader.read('!6B'))
+        reader.skip(2)
+        obj.config = reader.read('!L')[0]
+        obj.mask = reader.read('!L')[0]
+        obj.advertise = reader.read('!L')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.port_no != other.port_no: return False
+        if self.hw_addr != other.hw_addr: return False
+        if self.config != other.config: return False
+        if self.mask != other.mask: return False
+        if self.advertise != other.advertise: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("port_mod {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("port_no = ");
+                q.text(util.pretty_port(self.port_no))
+                q.text(","); q.breakable()
+                q.text("hw_addr = ");
+                q.text(util.pretty_mac(self.hw_addr))
+                q.text(","); q.breakable()
+                q.text("config = ");
+                q.text("%#x" % self.config)
+                q.text(","); q.breakable()
+                q.text("mask = ");
+                q.text("%#x" % self.mask)
+                q.text(","); q.breakable()
+                q.text("advertise = ");
+                q.text("%#x" % self.advertise)
+            q.breakable()
+        q.text('}')
+
+class port_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REPLY
+    stats_type = const.OFPST_PORT
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.entries]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = port_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_PORT)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.entries = loxi.generic_util.unpack_list(reader, common.port_stats_entry.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.entries != other.entries: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("port_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("entries = ");
+                q.pp(self.entries)
+            q.breakable()
+        q.text('}')
+
+class port_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REQUEST
+    stats_type = const.OFPST_PORT
+
+    def __init__(self, xid=None, flags=None, port_no=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if port_no != None:
+            self.port_no = port_no
+        else:
+            self.port_no = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!L", self.port_no))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = port_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_PORT)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.port_no = reader.read('!L')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.port_no != other.port_no: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("port_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("port_no = ");
+                q.text(util.pretty_port(self.port_no))
+            q.breakable()
+        q.text('}')
+
+class port_status(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_PORT_STATUS
+
+    def __init__(self, xid=None, reason=None, desc=None):
+        self.xid = xid
+        if reason != None:
+            self.reason = reason
+        else:
+            self.reason = 0
+        if desc != None:
+            self.desc = desc
+        else:
+            self.desc = common.port_desc()
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!B", self.reason))
+        packed.append('\x00' * 7)
+        packed.append(self.desc.pack())
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = port_status()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_PORT_STATUS)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.reason = reader.read('!B')[0]
+        reader.skip(7)
+        obj.desc = common.port_desc.unpack(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.reason != other.reason: return False
+        if self.desc != other.desc: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("port_status {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("reason = ");
+                q.text("%#x" % self.reason)
+                q.text(","); q.breakable()
+                q.text("desc = ");
+                q.pp(self.desc)
+            q.breakable()
+        q.text('}')
+
+class queue_get_config_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_QUEUE_GET_CONFIG_REPLY
+
+    def __init__(self, xid=None, port=None, queues=None):
+        self.xid = xid
+        if port != None:
+            self.port = port
+        else:
+            self.port = 0
+        if queues != None:
+            self.queues = queues
+        else:
+            self.queues = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.port))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.queues]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = queue_get_config_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_QUEUE_GET_CONFIG_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.port = reader.read('!L')[0]
+        reader.skip(4)
+        obj.queues = common.unpack_list_packet_queue(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.port != other.port: return False
+        if self.queues != other.queues: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("queue_get_config_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("port = ");
+                q.text(util.pretty_port(self.port))
+                q.text(","); q.breakable()
+                q.text("queues = ");
+                q.pp(self.queues)
+            q.breakable()
+        q.text('}')
+
+class queue_get_config_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_QUEUE_GET_CONFIG_REQUEST
+
+    def __init__(self, xid=None, port=None):
+        self.xid = xid
+        if port != None:
+            self.port = port
+        else:
+            self.port = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.port))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = queue_get_config_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_QUEUE_GET_CONFIG_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.port = reader.read('!L')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.port != other.port: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("queue_get_config_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("port = ");
+                q.text(util.pretty_port(self.port))
+            q.breakable()
+        q.text('}')
+
+class queue_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REPLY
+    stats_type = const.OFPST_QUEUE
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.entries]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = queue_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_QUEUE)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.entries = loxi.generic_util.unpack_list(reader, common.queue_stats_entry.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.entries != other.entries: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("queue_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("entries = ");
+                q.pp(self.entries)
+            q.breakable()
+        q.text('}')
+
+class queue_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REQUEST
+    stats_type = const.OFPST_QUEUE
+
+    def __init__(self, xid=None, flags=None, port_no=None, queue_id=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if port_no != None:
+            self.port_no = port_no
+        else:
+            self.port_no = 0
+        if queue_id != None:
+            self.queue_id = queue_id
+        else:
+            self.queue_id = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!L", self.port_no))
+        packed.append(struct.pack("!L", self.queue_id))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = queue_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_QUEUE)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.port_no = reader.read('!L')[0]
+        obj.queue_id = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.port_no != other.port_no: return False
+        if self.queue_id != other.queue_id: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("queue_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("port_no = ");
+                q.text(util.pretty_port(self.port_no))
+                q.text(","); q.breakable()
+                q.text("queue_id = ");
+                q.text("%#x" % self.queue_id)
+            q.breakable()
+        q.text('}')
+
+class set_config(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_SET_CONFIG
+
+    def __init__(self, xid=None, flags=None, miss_send_len=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if miss_send_len != None:
+            self.miss_send_len = miss_send_len
+        else:
+            self.miss_send_len = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append(struct.pack("!H", self.miss_send_len))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = set_config()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_SET_CONFIG)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.flags = reader.read('!H')[0]
+        obj.miss_send_len = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.miss_send_len != other.miss_send_len: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("set_config {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("miss_send_len = ");
+                q.text("%#x" % self.miss_send_len)
+            q.breakable()
+        q.text('}')
+
+class table_mod(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_TABLE_MOD
+
+    def __init__(self, xid=None, table_id=None, config=None):
+        self.xid = xid
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if config != None:
+            self.config = config
+        else:
+            self.config = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append('\x00' * 3)
+        packed.append(struct.pack("!L", self.config))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = table_mod()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_TABLE_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.table_id = reader.read('!B')[0]
+        reader.skip(3)
+        obj.config = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.table_id != other.table_id: return False
+        if self.config != other.config: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_mod {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("config = ");
+                q.text("%#x" % self.config)
+            q.breakable()
+        q.text('}')
+
+class table_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REPLY
+    stats_type = const.OFPST_TABLE
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.entries]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = table_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_TABLE)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.entries = loxi.generic_util.unpack_list(reader, common.table_stats_entry.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.entries != other.entries: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("entries = ");
+                q.pp(self.entries)
+            q.breakable()
+        q.text('}')
+
+class table_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REQUEST
+    stats_type = const.OFPST_TABLE
+
+    def __init__(self, xid=None, flags=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = table_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_TABLE)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+            q.breakable()
+        q.text('}')
+
+
+def parse_header(buf):
+    if len(buf) < 8:
+        raise loxi.ProtocolError("too short to be an OpenFlow message")
+    return struct.unpack_from("!BBHL", buf)
+
+def parse_message(buf):
+    msg_ver, msg_type, msg_len, msg_xid = parse_header(buf)
+    if msg_ver != const.OFP_VERSION and msg_type != ofp.OFPT_HELLO:
+        raise loxi.ProtocolError("wrong OpenFlow version")
+    if len(buf) != msg_len:
+        raise loxi.ProtocolError("incorrect message size")
+    if msg_type in parsers:
+        return parsers[msg_type](buf)
+    else:
+        raise loxi.ProtocolError("unexpected message type")
+
+def parse_flow_mod(buf):
+    if len(buf) < 56 + 2:
+        raise loxi.ProtocolError("message too short")
+    cmd, = struct.unpack_from("!H", buf, 56)
+    if cmd in flow_mod_parsers:
+        return flow_mod_parsers[cmd](buf)
+    else:
+        raise loxi.ProtocolError("unexpected flow mod cmd %u" % cmd)
+
+def parse_stats_reply(buf):
+    if len(buf) < 8 + 2:
+        raise loxi.ProtocolError("message too short")
+    stats_type, = struct.unpack_from("!H", buf, 8)
+    if stats_type in stats_reply_parsers:
+        return stats_reply_parsers[stats_type](buf)
+    else:
+        raise loxi.ProtocolError("unexpected stats type %u" % stats_type)
+
+def parse_stats_request(buf):
+    if len(buf) < 8 + 2:
+        raise loxi.ProtocolError("message too short")
+    stats_type, = struct.unpack_from("!H", buf, 8)
+    if stats_type in stats_request_parsers:
+        return stats_request_parsers[stats_type](buf)
+    else:
+        raise loxi.ProtocolError("unexpected stats type %u" % stats_type)
+
+def parse_experimenter(buf):
+    if len(buf) < 16:
+        raise loxi.ProtocolError("experimenter message too short")
+
+    experimenter, = struct.unpack_from("!L", buf, 8)
+    if experimenter == 0x005c16c7: # Big Switch Networks
+        subtype, = struct.unpack_from("!L", buf, 12)
+    elif experimenter == 0x00002320: # Nicira
+        subtype, = struct.unpack_from("!L", buf, 12)
+    else:
+        raise loxi.ProtocolError("unexpected experimenter id %#x" % experimenter)
+
+    if subtype in experimenter_parsers[experimenter]:
+        return experimenter_parsers[experimenter][subtype](buf)
+    else:
+        raise loxi.ProtocolError("unexpected experimenter %#x subtype %#x" % (experimenter, subtype))
+
+parsers = {
+    const.OFPT_BARRIER_REPLY : barrier_reply.unpack,
+    const.OFPT_BARRIER_REQUEST : barrier_request.unpack,
+    const.OFPT_ECHO_REPLY : echo_reply.unpack,
+    const.OFPT_ECHO_REQUEST : echo_request.unpack,
+    const.OFPT_ERROR : error_msg.unpack,
+    const.OFPT_EXPERIMENTER : parse_experimenter,
+    const.OFPT_FEATURES_REPLY : features_reply.unpack,
+    const.OFPT_FEATURES_REQUEST : features_request.unpack,
+    const.OFPT_FLOW_MOD : parse_flow_mod,
+    const.OFPT_FLOW_REMOVED : flow_removed.unpack,
+    const.OFPT_GET_CONFIG_REPLY : get_config_reply.unpack,
+    const.OFPT_GET_CONFIG_REQUEST : get_config_request.unpack,
+    const.OFPT_GROUP_MOD : group_mod.unpack,
+    const.OFPT_HELLO : hello.unpack,
+    const.OFPT_PACKET_IN : packet_in.unpack,
+    const.OFPT_PACKET_OUT : packet_out.unpack,
+    const.OFPT_PORT_MOD : port_mod.unpack,
+    const.OFPT_PORT_STATUS : port_status.unpack,
+    const.OFPT_QUEUE_GET_CONFIG_REPLY : queue_get_config_reply.unpack,
+    const.OFPT_QUEUE_GET_CONFIG_REQUEST : queue_get_config_request.unpack,
+    const.OFPT_SET_CONFIG : set_config.unpack,
+    const.OFPT_STATS_REPLY : parse_stats_reply,
+    const.OFPT_STATS_REQUEST : parse_stats_request,
+    const.OFPT_TABLE_MOD : table_mod.unpack,
+}
+
+flow_mod_parsers = {
+    const.OFPFC_ADD : flow_add.unpack,
+    const.OFPFC_MODIFY : flow_modify.unpack,
+    const.OFPFC_MODIFY_STRICT : flow_modify_strict.unpack,
+    const.OFPFC_DELETE : flow_delete.unpack,
+    const.OFPFC_DELETE_STRICT : flow_delete_strict.unpack,
+}
+
+stats_reply_parsers = {
+    const.OFPST_DESC : desc_stats_reply.unpack,
+    const.OFPST_FLOW : flow_stats_reply.unpack,
+    const.OFPST_AGGREGATE : aggregate_stats_reply.unpack,
+    const.OFPST_TABLE : table_stats_reply.unpack,
+    const.OFPST_PORT : port_stats_reply.unpack,
+    const.OFPST_QUEUE : queue_stats_reply.unpack,
+    const.OFPST_EXPERIMENTER : experimenter_stats_reply.unpack,
+}
+
+stats_request_parsers = {
+    const.OFPST_DESC : desc_stats_request.unpack,
+    const.OFPST_FLOW : flow_stats_request.unpack,
+    const.OFPST_AGGREGATE : aggregate_stats_request.unpack,
+    const.OFPST_TABLE : table_stats_request.unpack,
+    const.OFPST_PORT : port_stats_request.unpack,
+    const.OFPST_QUEUE : queue_stats_request.unpack,
+    const.OFPST_EXPERIMENTER : experimenter_stats_request.unpack,
+}
+
+experimenter_parsers = {
+}
diff --git a/src/python/loxi/of11/util.py b/src/python/loxi/of11/util.py
new file mode 100644
index 0000000..45aa2d0
--- /dev/null
+++ b/src/python/loxi/of11/util.py
@@ -0,0 +1,45 @@
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+
+# Automatically generated by LOXI from template util.py
+# Do not modify
+
+import loxi
+import const
+import struct
+
+def pretty_mac(mac):
+    return ':'.join(["%02x" % x for x in mac])
+
+def pretty_ipv4(v):
+    return "%d.%d.%d.%d" % ((v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF)
+
+def pretty_flags(v, flag_names):
+    set_flags = []
+    for flag_name in flag_names:
+        flag_value = getattr(const, flag_name)
+        if v & flag_value == flag_value:
+            set_flags.append(flag_name)
+        elif v & flag_value:
+            set_flags.append('%s&%#x' % (flag_name, v & flag_value))
+        v &= ~flag_value
+    if v:
+        set_flags.append("%#x" % v)
+    return '|'.join(set_flags) or '0'
+
+def pretty_wildcards(v):
+    if v == const.OFPFW_ALL:
+        return 'OFPFW_ALL'
+    flag_names = ['OFPFW_IN_PORT', 'OFPFW_DL_VLAN', 'OFPFW_DL_SRC', 'OFPFW_DL_DST',
+                  'OFPFW_DL_TYPE', 'OFPFW_NW_PROTO', 'OFPFW_TP_SRC', 'OFPFW_TP_DST',
+                  'OFPFW_NW_SRC_MASK', 'OFPFW_NW_DST_MASK', 'OFPFW_DL_VLAN_PCP',
+                  'OFPFW_NW_TOS']
+    return pretty_flags(v, flag_names)
+
+def pretty_port(v):
+    named_ports = [(k,v2) for (k,v2) in const.__dict__.iteritems() if k.startswith('OFPP_')]
+    for (k, v2) in named_ports:
+        if v == v2:
+            return k
+    return v
diff --git a/src/python/loxi/of12/__init__.py b/src/python/loxi/of12/__init__.py
new file mode 100644
index 0000000..5610646
--- /dev/null
+++ b/src/python/loxi/of12/__init__.py
@@ -0,0 +1,13 @@
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+
+# Automatically generated by LOXI from template init.py
+# Do not modify
+
+import action, common, const, message
+import instruction
+import oxm
+from const import *
+from common import *
+from loxi import ProtocolError
diff --git a/src/python/loxi/of12/action.py b/src/python/loxi/of12/action.py
new file mode 100644
index 0000000..8775b88
--- /dev/null
+++ b/src/python/loxi/of12/action.py
@@ -0,0 +1,1006 @@
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+
+# Automatically generated by LOXI from template action.py
+# Do not modify
+
+import struct
+import const
+import util
+import loxi.generic_util
+import loxi
+
+def unpack_list(reader):
+    def deserializer(reader, typ):
+        parser = parsers.get(typ)
+        if not parser: raise loxi.ProtocolError("unknown action type %d" % typ)
+        return parser(reader)
+    return loxi.generic_util.unpack_list_tlv16(reader, deserializer)
+
+class Action(object):
+    type = None # override in subclass
+    pass
+
+class bsn_mirror(Action):
+    type = const.OFPAT_EXPERIMENTER
+    experimenter = 0x5c16c7
+    subtype = 1
+
+    def __init__(self, dest_port=None, vlan_tag=None, copy_stage=None):
+        if dest_port != None:
+            self.dest_port = dest_port
+        else:
+            self.dest_port = 0
+        if vlan_tag != None:
+            self.vlan_tag = vlan_tag
+        else:
+            self.vlan_tag = 0
+        if copy_stage != None:
+            self.copy_stage = copy_stage
+        else:
+            self.copy_stage = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        packed.append(struct.pack("!L", self.dest_port))
+        packed.append(struct.pack("!L", self.vlan_tag))
+        packed.append(struct.pack("!B", self.copy_stage))
+        packed.append('\x00' * 3)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = bsn_mirror()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_EXPERIMENTER)
+        _len = reader.read('!H')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 1)
+        obj.dest_port = reader.read('!L')[0]
+        obj.vlan_tag = reader.read('!L')[0]
+        obj.copy_stage = reader.read('!B')[0]
+        reader.skip(3)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.dest_port != other.dest_port: return False
+        if self.vlan_tag != other.vlan_tag: return False
+        if self.copy_stage != other.copy_stage: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_mirror {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("dest_port = ");
+                q.text("%#x" % self.dest_port)
+                q.text(","); q.breakable()
+                q.text("vlan_tag = ");
+                q.text("%#x" % self.vlan_tag)
+                q.text(","); q.breakable()
+                q.text("copy_stage = ");
+                q.text("%#x" % self.copy_stage)
+            q.breakable()
+        q.text('}')
+
+class bsn_set_tunnel_dst(Action):
+    type = const.OFPAT_EXPERIMENTER
+    experimenter = 0x5c16c7
+    subtype = 2
+
+    def __init__(self, dst=None):
+        if dst != None:
+            self.dst = dst
+        else:
+            self.dst = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        packed.append(struct.pack("!L", self.dst))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = bsn_set_tunnel_dst()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_EXPERIMENTER)
+        _len = reader.read('!H')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 2)
+        obj.dst = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.dst != other.dst: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_set_tunnel_dst {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("dst = ");
+                q.text("%#x" % self.dst)
+            q.breakable()
+        q.text('}')
+
+class copy_ttl_in(Action):
+    type = const.OFPAT_COPY_TTL_IN
+
+    def __init__(self):
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = copy_ttl_in()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_COPY_TTL_IN)
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("copy_ttl_in {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+            q.breakable()
+        q.text('}')
+
+class copy_ttl_out(Action):
+    type = const.OFPAT_COPY_TTL_OUT
+
+    def __init__(self):
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = copy_ttl_out()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_COPY_TTL_OUT)
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("copy_ttl_out {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+            q.breakable()
+        q.text('}')
+
+class dec_mpls_ttl(Action):
+    type = const.OFPAT_DEC_MPLS_TTL
+
+    def __init__(self):
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = dec_mpls_ttl()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_DEC_MPLS_TTL)
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("dec_mpls_ttl {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+            q.breakable()
+        q.text('}')
+
+class dec_nw_ttl(Action):
+    type = const.OFPAT_DEC_NW_TTL
+
+    def __init__(self):
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = dec_nw_ttl()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_DEC_NW_TTL)
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("dec_nw_ttl {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+            q.breakable()
+        q.text('}')
+
+class group(Action):
+    type = const.OFPAT_GROUP
+
+    def __init__(self, group_id=None):
+        if group_id != None:
+            self.group_id = group_id
+        else:
+            self.group_id = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!L", self.group_id))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = group()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_GROUP)
+        _len = reader.read('!H')[0]
+        obj.group_id = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.group_id != other.group_id: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("group_id = ");
+                q.text("%#x" % self.group_id)
+            q.breakable()
+        q.text('}')
+
+class nicira_dec_ttl(Action):
+    type = const.OFPAT_EXPERIMENTER
+    experimenter = 0x2320
+    subtype = 18
+
+    def __init__(self):
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!H", self.subtype))
+        packed.append('\x00' * 2)
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = nicira_dec_ttl()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_EXPERIMENTER)
+        _len = reader.read('!H')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x2320)
+        _subtype = reader.read('!H')[0]
+        assert(_subtype == 18)
+        reader.skip(2)
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("nicira_dec_ttl {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+            q.breakable()
+        q.text('}')
+
+class output(Action):
+    type = const.OFPAT_OUTPUT
+
+    def __init__(self, port=None, max_len=None):
+        if port != None:
+            self.port = port
+        else:
+            self.port = 0
+        if max_len != None:
+            self.max_len = max_len
+        else:
+            self.max_len = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!L", self.port))
+        packed.append(struct.pack("!H", self.max_len))
+        packed.append('\x00' * 6)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = output()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_OUTPUT)
+        _len = reader.read('!H')[0]
+        obj.port = reader.read('!L')[0]
+        obj.max_len = reader.read('!H')[0]
+        reader.skip(6)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.port != other.port: return False
+        if self.max_len != other.max_len: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("output {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("port = ");
+                q.text(util.pretty_port(self.port))
+                q.text(","); q.breakable()
+                q.text("max_len = ");
+                q.text("%#x" % self.max_len)
+            q.breakable()
+        q.text('}')
+
+class pop_mpls(Action):
+    type = const.OFPAT_POP_MPLS
+
+    def __init__(self, ethertype=None):
+        if ethertype != None:
+            self.ethertype = ethertype
+        else:
+            self.ethertype = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!H", self.ethertype))
+        packed.append('\x00' * 2)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = pop_mpls()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_POP_MPLS)
+        _len = reader.read('!H')[0]
+        obj.ethertype = reader.read('!H')[0]
+        reader.skip(2)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.ethertype != other.ethertype: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("pop_mpls {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("ethertype = ");
+                q.text("%#x" % self.ethertype)
+            q.breakable()
+        q.text('}')
+
+class pop_vlan(Action):
+    type = const.OFPAT_POP_VLAN
+
+    def __init__(self):
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = pop_vlan()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_POP_VLAN)
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("pop_vlan {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+            q.breakable()
+        q.text('}')
+
+class push_mpls(Action):
+    type = const.OFPAT_PUSH_MPLS
+
+    def __init__(self, ethertype=None):
+        if ethertype != None:
+            self.ethertype = ethertype
+        else:
+            self.ethertype = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!H", self.ethertype))
+        packed.append('\x00' * 2)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = push_mpls()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_PUSH_MPLS)
+        _len = reader.read('!H')[0]
+        obj.ethertype = reader.read('!H')[0]
+        reader.skip(2)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.ethertype != other.ethertype: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("push_mpls {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("ethertype = ");
+                q.text("%#x" % self.ethertype)
+            q.breakable()
+        q.text('}')
+
+class push_vlan(Action):
+    type = const.OFPAT_PUSH_VLAN
+
+    def __init__(self, ethertype=None):
+        if ethertype != None:
+            self.ethertype = ethertype
+        else:
+            self.ethertype = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!H", self.ethertype))
+        packed.append('\x00' * 2)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = push_vlan()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_PUSH_VLAN)
+        _len = reader.read('!H')[0]
+        obj.ethertype = reader.read('!H')[0]
+        reader.skip(2)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.ethertype != other.ethertype: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("push_vlan {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("ethertype = ");
+                q.text("%#x" % self.ethertype)
+            q.breakable()
+        q.text('}')
+
+class set_field(Action):
+    type = const.OFPAT_SET_FIELD
+
+    def __init__(self, field=None):
+        if field != None:
+            self.field = field
+        else:
+            self.field = ""
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(self.field)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = set_field()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_FIELD)
+        _len = reader.read('!H')[0]
+        obj.field = str(reader.read_all())
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.field != other.field: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("set_field {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("field = ");
+                q.pp(self.field)
+            q.breakable()
+        q.text('}')
+
+class set_mpls_ttl(Action):
+    type = const.OFPAT_SET_MPLS_TTL
+
+    def __init__(self, mpls_ttl=None):
+        if mpls_ttl != None:
+            self.mpls_ttl = mpls_ttl
+        else:
+            self.mpls_ttl = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!B", self.mpls_ttl))
+        packed.append('\x00' * 3)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = set_mpls_ttl()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_MPLS_TTL)
+        _len = reader.read('!H')[0]
+        obj.mpls_ttl = reader.read('!B')[0]
+        reader.skip(3)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.mpls_ttl != other.mpls_ttl: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("set_mpls_ttl {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("mpls_ttl = ");
+                q.text("%#x" % self.mpls_ttl)
+            q.breakable()
+        q.text('}')
+
+class set_nw_ttl(Action):
+    type = const.OFPAT_SET_NW_TTL
+
+    def __init__(self, nw_ttl=None):
+        if nw_ttl != None:
+            self.nw_ttl = nw_ttl
+        else:
+            self.nw_ttl = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!B", self.nw_ttl))
+        packed.append('\x00' * 3)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = set_nw_ttl()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_NW_TTL)
+        _len = reader.read('!H')[0]
+        obj.nw_ttl = reader.read('!B')[0]
+        reader.skip(3)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.nw_ttl != other.nw_ttl: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("set_nw_ttl {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("nw_ttl = ");
+                q.text("%#x" % self.nw_ttl)
+            q.breakable()
+        q.text('}')
+
+class set_queue(Action):
+    type = const.OFPAT_SET_QUEUE
+
+    def __init__(self, queue_id=None):
+        if queue_id != None:
+            self.queue_id = queue_id
+        else:
+            self.queue_id = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!L", self.queue_id))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = set_queue()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_QUEUE)
+        _len = reader.read('!H')[0]
+        obj.queue_id = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.queue_id != other.queue_id: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("set_queue {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("queue_id = ");
+                q.text("%#x" % self.queue_id)
+            q.breakable()
+        q.text('}')
+
+
+def parse_experimenter(reader):
+
+    experimenter, = reader.peek("!4xL")
+    if experimenter == 0x005c16c7: # Big Switch Networks
+        subtype, = reader.peek("!8xL")
+    elif experimenter == 0x00002320: # Nicira
+        subtype, = reader.peek("!8xH")
+    else:
+        raise loxi.ProtocolError("unexpected experimenter id %#x" % experimenter)
+
+    if subtype in experimenter_parsers[experimenter]:
+        return experimenter_parsers[experimenter][subtype](reader)
+    else:
+        raise loxi.ProtocolError("unexpected BSN experimenter subtype %#x" % subtype)
+
+parsers = {
+    const.OFPAT_COPY_TTL_IN : copy_ttl_in.unpack,
+    const.OFPAT_COPY_TTL_OUT : copy_ttl_out.unpack,
+    const.OFPAT_DEC_MPLS_TTL : dec_mpls_ttl.unpack,
+    const.OFPAT_DEC_NW_TTL : dec_nw_ttl.unpack,
+    const.OFPAT_EXPERIMENTER : parse_experimenter,
+    const.OFPAT_GROUP : group.unpack,
+    const.OFPAT_OUTPUT : output.unpack,
+    const.OFPAT_POP_MPLS : pop_mpls.unpack,
+    const.OFPAT_POP_VLAN : pop_vlan.unpack,
+    const.OFPAT_PUSH_MPLS : push_mpls.unpack,
+    const.OFPAT_PUSH_VLAN : push_vlan.unpack,
+    const.OFPAT_SET_FIELD : set_field.unpack,
+    const.OFPAT_SET_MPLS_TTL : set_mpls_ttl.unpack,
+    const.OFPAT_SET_NW_TTL : set_nw_ttl.unpack,
+    const.OFPAT_SET_QUEUE : set_queue.unpack,
+}
+
+experimenter_parsers = {
+}
diff --git a/src/python/loxi/of12/common.py b/src/python/loxi/of12/common.py
new file mode 100644
index 0000000..13cc2f4
--- /dev/null
+++ b/src/python/loxi/of12/common.py
@@ -0,0 +1,1512 @@
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+
+# Automatically generated by LOXI from template common.py
+# Do not modify
+
+import sys
+import struct
+import action
+import instruction # for unpack_list
+import const
+import util
+import loxi.generic_util
+
+import oxm
+
+# HACK make this module visible as 'common' to simplify code generation
+common = sys.modules[__name__]
+
+def unpack_list_flow_stats_entry(reader):
+    return loxi.generic_util.unpack_list_lv16(reader, flow_stats_entry.unpack)
+
+def unpack_list_queue_prop(reader):
+    def deserializer(reader, typ):
+        if typ == const.OFPQT_MIN_RATE:
+            return queue_prop_min_rate.unpack(reader)
+        else:
+            raise loxi.ProtocolError("unknown queue prop %d" % typ)
+    return loxi.generic_util.unpack_list_tlv16(reader, deserializer)
+
+def unpack_list_packet_queue(reader):
+    def wrapper(reader):
+        length, = reader.peek('!4xH')
+        return packet_queue.unpack(reader.slice(length))
+    return loxi.generic_util.unpack_list(reader, wrapper)
+
+def unpack_list_hello_elem(reader):
+    def deserializer(reader, typ):
+        if typ == const.OFPHET_VERSIONBITMAP:
+            return hello_elem_versionbitmap.unpack(reader)
+        else:
+            return None
+    return [x for x in loxi.generic_util.unpack_list_tlv16(reader, deserializer) if x != None]
+
+def unpack_list_bucket(reader):
+    return loxi.generic_util.unpack_list_lv16(reader, bucket.unpack)
+
+def unpack_list_group_desc_stats_entry(reader):
+    return loxi.generic_util.unpack_list_lv16(reader, group_desc_stats_entry.unpack)
+
+def unpack_list_group_stats_entry(reader):
+    return loxi.generic_util.unpack_list_lv16(reader, group_stats_entry.unpack)
+
+def unpack_list_meter_stats(reader):
+    def wrapper(reader):
+        length, = reader.peek('!4xH')
+        return meter_stats.unpack(reader.slice(length))
+    return loxi.generic_util.unpack_list(reader, wrapper)
+
+class bsn_interface(object):
+
+    def __init__(self, hw_addr=None, name=None, ipv4_addr=None, ipv4_netmask=None):
+        if hw_addr != None:
+            self.hw_addr = hw_addr
+        else:
+            self.hw_addr = [0,0,0,0,0,0]
+        if name != None:
+            self.name = name
+        else:
+            self.name = ""
+        if ipv4_addr != None:
+            self.ipv4_addr = ipv4_addr
+        else:
+            self.ipv4_addr = 0
+        if ipv4_netmask != None:
+            self.ipv4_netmask = ipv4_netmask
+        else:
+            self.ipv4_netmask = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!6B", *self.hw_addr))
+        packed.append('\x00' * 2)
+        packed.append(struct.pack("!16s", self.name))
+        packed.append(struct.pack("!L", self.ipv4_addr))
+        packed.append(struct.pack("!L", self.ipv4_netmask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = bsn_interface()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.hw_addr = list(reader.read('!6B'))
+        reader.skip(2)
+        obj.name = reader.read("!16s")[0].rstrip("\x00")
+        obj.ipv4_addr = reader.read('!L')[0]
+        obj.ipv4_netmask = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.hw_addr != other.hw_addr: return False
+        if self.name != other.name: return False
+        if self.ipv4_addr != other.ipv4_addr: return False
+        if self.ipv4_netmask != other.ipv4_netmask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_interface {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("hw_addr = ");
+                q.text(util.pretty_mac(self.hw_addr))
+                q.text(","); q.breakable()
+                q.text("name = ");
+                q.pp(self.name)
+                q.text(","); q.breakable()
+                q.text("ipv4_addr = ");
+                q.text(util.pretty_ipv4(self.ipv4_addr))
+                q.text(","); q.breakable()
+                q.text("ipv4_netmask = ");
+                q.text(util.pretty_ipv4(self.ipv4_netmask))
+            q.breakable()
+        q.text('}')
+
+class bucket(object):
+
+    def __init__(self, weight=None, watch_port=None, watch_group=None, actions=None):
+        if weight != None:
+            self.weight = weight
+        else:
+            self.weight = 0
+        if watch_port != None:
+            self.watch_port = watch_port
+        else:
+            self.watch_port = 0
+        if watch_group != None:
+            self.watch_group = watch_group
+        else:
+            self.watch_group = 0
+        if actions != None:
+            self.actions = actions
+        else:
+            self.actions = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 0
+        packed.append(struct.pack("!H", self.weight))
+        packed.append(struct.pack("!L", self.watch_port))
+        packed.append(struct.pack("!L", self.watch_group))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.actions]))
+        length = sum([len(x) for x in packed])
+        packed[0] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = bucket()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _len = reader.read('!H')[0]
+        obj.weight = reader.read('!H')[0]
+        obj.watch_port = reader.read('!L')[0]
+        obj.watch_group = reader.read('!L')[0]
+        reader.skip(4)
+        obj.actions = action.unpack_list(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.weight != other.weight: return False
+        if self.watch_port != other.watch_port: return False
+        if self.watch_group != other.watch_group: return False
+        if self.actions != other.actions: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bucket {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("weight = ");
+                q.text("%#x" % self.weight)
+                q.text(","); q.breakable()
+                q.text("watch_port = ");
+                q.text(util.pretty_port(self.watch_port))
+                q.text(","); q.breakable()
+                q.text("watch_group = ");
+                q.text("%#x" % self.watch_group)
+                q.text(","); q.breakable()
+                q.text("actions = ");
+                q.pp(self.actions)
+            q.breakable()
+        q.text('}')
+
+class bucket_counter(object):
+
+    def __init__(self, packet_count=None, byte_count=None):
+        if packet_count != None:
+            self.packet_count = packet_count
+        else:
+            self.packet_count = 0
+        if byte_count != None:
+            self.byte_count = byte_count
+        else:
+            self.byte_count = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!Q", self.packet_count))
+        packed.append(struct.pack("!Q", self.byte_count))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = bucket_counter()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.packet_count = reader.read('!Q')[0]
+        obj.byte_count = reader.read('!Q')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.packet_count != other.packet_count: return False
+        if self.byte_count != other.byte_count: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bucket_counter {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("packet_count = ");
+                q.text("%#x" % self.packet_count)
+                q.text(","); q.breakable()
+                q.text("byte_count = ");
+                q.text("%#x" % self.byte_count)
+            q.breakable()
+        q.text('}')
+
+class flow_stats_entry(object):
+
+    def __init__(self, table_id=None, duration_sec=None, duration_nsec=None, priority=None, idle_timeout=None, hard_timeout=None, cookie=None, packet_count=None, byte_count=None, match=None, instructions=None):
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if duration_sec != None:
+            self.duration_sec = duration_sec
+        else:
+            self.duration_sec = 0
+        if duration_nsec != None:
+            self.duration_nsec = duration_nsec
+        else:
+            self.duration_nsec = 0
+        if priority != None:
+            self.priority = priority
+        else:
+            self.priority = 0
+        if idle_timeout != None:
+            self.idle_timeout = idle_timeout
+        else:
+            self.idle_timeout = 0
+        if hard_timeout != None:
+            self.hard_timeout = hard_timeout
+        else:
+            self.hard_timeout = 0
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if packet_count != None:
+            self.packet_count = packet_count
+        else:
+            self.packet_count = 0
+        if byte_count != None:
+            self.byte_count = byte_count
+        else:
+            self.byte_count = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+        if instructions != None:
+            self.instructions = instructions
+        else:
+            self.instructions = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 0
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append('\x00' * 1)
+        packed.append(struct.pack("!L", self.duration_sec))
+        packed.append(struct.pack("!L", self.duration_nsec))
+        packed.append(struct.pack("!H", self.priority))
+        packed.append(struct.pack("!H", self.idle_timeout))
+        packed.append(struct.pack("!H", self.hard_timeout))
+        packed.append('\x00' * 6)
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!Q", self.packet_count))
+        packed.append(struct.pack("!Q", self.byte_count))
+        packed.append(self.match.pack())
+        packed.append("".join([x.pack() for x in self.instructions]))
+        length = sum([len(x) for x in packed])
+        packed[0] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = flow_stats_entry()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _length = reader.read('!H')[0]
+        obj.table_id = reader.read('!B')[0]
+        reader.skip(1)
+        obj.duration_sec = reader.read('!L')[0]
+        obj.duration_nsec = reader.read('!L')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        reader.skip(6)
+        obj.cookie = reader.read('!Q')[0]
+        obj.packet_count = reader.read('!Q')[0]
+        obj.byte_count = reader.read('!Q')[0]
+        obj.match = common.match.unpack(reader)
+        obj.instructions = instruction.unpack_list(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.table_id != other.table_id: return False
+        if self.duration_sec != other.duration_sec: return False
+        if self.duration_nsec != other.duration_nsec: return False
+        if self.priority != other.priority: return False
+        if self.idle_timeout != other.idle_timeout: return False
+        if self.hard_timeout != other.hard_timeout: return False
+        if self.cookie != other.cookie: return False
+        if self.packet_count != other.packet_count: return False
+        if self.byte_count != other.byte_count: return False
+        if self.match != other.match: return False
+        if self.instructions != other.instructions: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_stats_entry {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("duration_sec = ");
+                q.text("%#x" % self.duration_sec)
+                q.text(","); q.breakable()
+                q.text("duration_nsec = ");
+                q.text("%#x" % self.duration_nsec)
+                q.text(","); q.breakable()
+                q.text("priority = ");
+                q.text("%#x" % self.priority)
+                q.text(","); q.breakable()
+                q.text("idle_timeout = ");
+                q.text("%#x" % self.idle_timeout)
+                q.text(","); q.breakable()
+                q.text("hard_timeout = ");
+                q.text("%#x" % self.hard_timeout)
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("packet_count = ");
+                q.text("%#x" % self.packet_count)
+                q.text(","); q.breakable()
+                q.text("byte_count = ");
+                q.text("%#x" % self.byte_count)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+                q.text(","); q.breakable()
+                q.text("instructions = ");
+                q.pp(self.instructions)
+            q.breakable()
+        q.text('}')
+
+class group_desc_stats_entry(object):
+
+    def __init__(self, type=None, group_id=None, buckets=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        if group_id != None:
+            self.group_id = group_id
+        else:
+            self.group_id = 0
+        if buckets != None:
+            self.buckets = buckets
+        else:
+            self.buckets = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 0
+        packed.append(struct.pack("!B", self.type))
+        packed.append('\x00' * 1)
+        packed.append(struct.pack("!L", self.group_id))
+        packed.append("".join([x.pack() for x in self.buckets]))
+        length = sum([len(x) for x in packed])
+        packed[0] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = group_desc_stats_entry()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _length = reader.read('!H')[0]
+        obj.type = reader.read('!B')[0]
+        reader.skip(1)
+        obj.group_id = reader.read('!L')[0]
+        obj.buckets = common.unpack_list_bucket(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        if self.group_id != other.group_id: return False
+        if self.buckets != other.buckets: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group_desc_stats_entry {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+                q.text(","); q.breakable()
+                q.text("group_id = ");
+                q.text("%#x" % self.group_id)
+                q.text(","); q.breakable()
+                q.text("buckets = ");
+                q.pp(self.buckets)
+            q.breakable()
+        q.text('}')
+
+class group_stats_entry(object):
+
+    def __init__(self, group_id=None, ref_count=None, packet_count=None, byte_count=None, bucket_stats=None):
+        if group_id != None:
+            self.group_id = group_id
+        else:
+            self.group_id = 0
+        if ref_count != None:
+            self.ref_count = ref_count
+        else:
+            self.ref_count = 0
+        if packet_count != None:
+            self.packet_count = packet_count
+        else:
+            self.packet_count = 0
+        if byte_count != None:
+            self.byte_count = byte_count
+        else:
+            self.byte_count = 0
+        if bucket_stats != None:
+            self.bucket_stats = bucket_stats
+        else:
+            self.bucket_stats = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 0
+        packed.append('\x00' * 2)
+        packed.append(struct.pack("!L", self.group_id))
+        packed.append(struct.pack("!L", self.ref_count))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!Q", self.packet_count))
+        packed.append(struct.pack("!Q", self.byte_count))
+        packed.append("".join([x.pack() for x in self.bucket_stats]))
+        length = sum([len(x) for x in packed])
+        packed[0] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = group_stats_entry()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _length = reader.read('!H')[0]
+        reader.skip(2)
+        obj.group_id = reader.read('!L')[0]
+        obj.ref_count = reader.read('!L')[0]
+        reader.skip(4)
+        obj.packet_count = reader.read('!Q')[0]
+        obj.byte_count = reader.read('!Q')[0]
+        obj.bucket_stats = loxi.generic_util.unpack_list(reader, common.bucket_counter.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.group_id != other.group_id: return False
+        if self.ref_count != other.ref_count: return False
+        if self.packet_count != other.packet_count: return False
+        if self.byte_count != other.byte_count: return False
+        if self.bucket_stats != other.bucket_stats: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group_stats_entry {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("group_id = ");
+                q.text("%#x" % self.group_id)
+                q.text(","); q.breakable()
+                q.text("ref_count = ");
+                q.text("%#x" % self.ref_count)
+                q.text(","); q.breakable()
+                q.text("packet_count = ");
+                q.text("%#x" % self.packet_count)
+                q.text(","); q.breakable()
+                q.text("byte_count = ");
+                q.text("%#x" % self.byte_count)
+                q.text(","); q.breakable()
+                q.text("bucket_stats = ");
+                q.pp(self.bucket_stats)
+            q.breakable()
+        q.text('}')
+
+class match_v3(object):
+    type = 1
+
+    def __init__(self, oxm_list=None):
+        if oxm_list != None:
+            self.oxm_list = oxm_list
+        else:
+            self.oxm_list = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 1
+        packed.append("".join([x.pack() for x in self.oxm_list]))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        packed.append('\x00' * ((length + 7)/8*8 - length))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = match_v3()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == 1)
+        _length = reader.read('!H')[0]
+        obj.oxm_list = oxm.unpack_list(reader.slice(_length-4))
+        reader.skip((_length + 7)/8*8 - _length)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.oxm_list != other.oxm_list: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("match_v3 {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("oxm_list = ");
+                q.pp(self.oxm_list)
+            q.breakable()
+        q.text('}')
+
+class packet_queue(object):
+
+    def __init__(self, queue_id=None, port=None, properties=None):
+        if queue_id != None:
+            self.queue_id = queue_id
+        else:
+            self.queue_id = 0
+        if port != None:
+            self.port = port
+        else:
+            self.port = 0
+        if properties != None:
+            self.properties = properties
+        else:
+            self.properties = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.queue_id))
+        packed.append(struct.pack("!L", self.port))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 2
+        packed.append('\x00' * 6)
+        packed.append("".join([x.pack() for x in self.properties]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = packet_queue()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.queue_id = reader.read('!L')[0]
+        obj.port = reader.read('!L')[0]
+        _len = reader.read('!H')[0]
+        reader.skip(6)
+        obj.properties = common.unpack_list_queue_prop(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.queue_id != other.queue_id: return False
+        if self.port != other.port: return False
+        if self.properties != other.properties: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("packet_queue {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("queue_id = ");
+                q.text("%#x" % self.queue_id)
+                q.text(","); q.breakable()
+                q.text("port = ");
+                q.text(util.pretty_port(self.port))
+                q.text(","); q.breakable()
+                q.text("properties = ");
+                q.pp(self.properties)
+            q.breakable()
+        q.text('}')
+
+class port_desc(object):
+
+    def __init__(self, port_no=None, hw_addr=None, name=None, config=None, state=None, curr=None, advertised=None, supported=None, peer=None, curr_speed=None, max_speed=None):
+        if port_no != None:
+            self.port_no = port_no
+        else:
+            self.port_no = 0
+        if hw_addr != None:
+            self.hw_addr = hw_addr
+        else:
+            self.hw_addr = [0,0,0,0,0,0]
+        if name != None:
+            self.name = name
+        else:
+            self.name = ""
+        if config != None:
+            self.config = config
+        else:
+            self.config = 0
+        if state != None:
+            self.state = state
+        else:
+            self.state = 0
+        if curr != None:
+            self.curr = curr
+        else:
+            self.curr = 0
+        if advertised != None:
+            self.advertised = advertised
+        else:
+            self.advertised = 0
+        if supported != None:
+            self.supported = supported
+        else:
+            self.supported = 0
+        if peer != None:
+            self.peer = peer
+        else:
+            self.peer = 0
+        if curr_speed != None:
+            self.curr_speed = curr_speed
+        else:
+            self.curr_speed = 0
+        if max_speed != None:
+            self.max_speed = max_speed
+        else:
+            self.max_speed = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.port_no))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!6B", *self.hw_addr))
+        packed.append('\x00' * 2)
+        packed.append(struct.pack("!16s", self.name))
+        packed.append(struct.pack("!L", self.config))
+        packed.append(struct.pack("!L", self.state))
+        packed.append(struct.pack("!L", self.curr))
+        packed.append(struct.pack("!L", self.advertised))
+        packed.append(struct.pack("!L", self.supported))
+        packed.append(struct.pack("!L", self.peer))
+        packed.append(struct.pack("!L", self.curr_speed))
+        packed.append(struct.pack("!L", self.max_speed))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = port_desc()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.port_no = reader.read('!L')[0]
+        reader.skip(4)
+        obj.hw_addr = list(reader.read('!6B'))
+        reader.skip(2)
+        obj.name = reader.read("!16s")[0].rstrip("\x00")
+        obj.config = reader.read('!L')[0]
+        obj.state = reader.read('!L')[0]
+        obj.curr = reader.read('!L')[0]
+        obj.advertised = reader.read('!L')[0]
+        obj.supported = reader.read('!L')[0]
+        obj.peer = reader.read('!L')[0]
+        obj.curr_speed = reader.read('!L')[0]
+        obj.max_speed = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.port_no != other.port_no: return False
+        if self.hw_addr != other.hw_addr: return False
+        if self.name != other.name: return False
+        if self.config != other.config: return False
+        if self.state != other.state: return False
+        if self.curr != other.curr: return False
+        if self.advertised != other.advertised: return False
+        if self.supported != other.supported: return False
+        if self.peer != other.peer: return False
+        if self.curr_speed != other.curr_speed: return False
+        if self.max_speed != other.max_speed: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("port_desc {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("port_no = ");
+                q.text(util.pretty_port(self.port_no))
+                q.text(","); q.breakable()
+                q.text("hw_addr = ");
+                q.text(util.pretty_mac(self.hw_addr))
+                q.text(","); q.breakable()
+                q.text("name = ");
+                q.pp(self.name)
+                q.text(","); q.breakable()
+                q.text("config = ");
+                q.text("%#x" % self.config)
+                q.text(","); q.breakable()
+                q.text("state = ");
+                q.text("%#x" % self.state)
+                q.text(","); q.breakable()
+                q.text("curr = ");
+                q.text("%#x" % self.curr)
+                q.text(","); q.breakable()
+                q.text("advertised = ");
+                q.text("%#x" % self.advertised)
+                q.text(","); q.breakable()
+                q.text("supported = ");
+                q.text("%#x" % self.supported)
+                q.text(","); q.breakable()
+                q.text("peer = ");
+                q.text("%#x" % self.peer)
+                q.text(","); q.breakable()
+                q.text("curr_speed = ");
+                q.text("%#x" % self.curr_speed)
+                q.text(","); q.breakable()
+                q.text("max_speed = ");
+                q.text("%#x" % self.max_speed)
+            q.breakable()
+        q.text('}')
+
+class port_stats_entry(object):
+
+    def __init__(self, port_no=None, rx_packets=None, tx_packets=None, rx_bytes=None, tx_bytes=None, rx_dropped=None, tx_dropped=None, rx_errors=None, tx_errors=None, rx_frame_err=None, rx_over_err=None, rx_crc_err=None, collisions=None):
+        if port_no != None:
+            self.port_no = port_no
+        else:
+            self.port_no = 0
+        if rx_packets != None:
+            self.rx_packets = rx_packets
+        else:
+            self.rx_packets = 0
+        if tx_packets != None:
+            self.tx_packets = tx_packets
+        else:
+            self.tx_packets = 0
+        if rx_bytes != None:
+            self.rx_bytes = rx_bytes
+        else:
+            self.rx_bytes = 0
+        if tx_bytes != None:
+            self.tx_bytes = tx_bytes
+        else:
+            self.tx_bytes = 0
+        if rx_dropped != None:
+            self.rx_dropped = rx_dropped
+        else:
+            self.rx_dropped = 0
+        if tx_dropped != None:
+            self.tx_dropped = tx_dropped
+        else:
+            self.tx_dropped = 0
+        if rx_errors != None:
+            self.rx_errors = rx_errors
+        else:
+            self.rx_errors = 0
+        if tx_errors != None:
+            self.tx_errors = tx_errors
+        else:
+            self.tx_errors = 0
+        if rx_frame_err != None:
+            self.rx_frame_err = rx_frame_err
+        else:
+            self.rx_frame_err = 0
+        if rx_over_err != None:
+            self.rx_over_err = rx_over_err
+        else:
+            self.rx_over_err = 0
+        if rx_crc_err != None:
+            self.rx_crc_err = rx_crc_err
+        else:
+            self.rx_crc_err = 0
+        if collisions != None:
+            self.collisions = collisions
+        else:
+            self.collisions = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.port_no))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!Q", self.rx_packets))
+        packed.append(struct.pack("!Q", self.tx_packets))
+        packed.append(struct.pack("!Q", self.rx_bytes))
+        packed.append(struct.pack("!Q", self.tx_bytes))
+        packed.append(struct.pack("!Q", self.rx_dropped))
+        packed.append(struct.pack("!Q", self.tx_dropped))
+        packed.append(struct.pack("!Q", self.rx_errors))
+        packed.append(struct.pack("!Q", self.tx_errors))
+        packed.append(struct.pack("!Q", self.rx_frame_err))
+        packed.append(struct.pack("!Q", self.rx_over_err))
+        packed.append(struct.pack("!Q", self.rx_crc_err))
+        packed.append(struct.pack("!Q", self.collisions))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = port_stats_entry()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.port_no = reader.read('!L')[0]
+        reader.skip(4)
+        obj.rx_packets = reader.read('!Q')[0]
+        obj.tx_packets = reader.read('!Q')[0]
+        obj.rx_bytes = reader.read('!Q')[0]
+        obj.tx_bytes = reader.read('!Q')[0]
+        obj.rx_dropped = reader.read('!Q')[0]
+        obj.tx_dropped = reader.read('!Q')[0]
+        obj.rx_errors = reader.read('!Q')[0]
+        obj.tx_errors = reader.read('!Q')[0]
+        obj.rx_frame_err = reader.read('!Q')[0]
+        obj.rx_over_err = reader.read('!Q')[0]
+        obj.rx_crc_err = reader.read('!Q')[0]
+        obj.collisions = reader.read('!Q')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.port_no != other.port_no: return False
+        if self.rx_packets != other.rx_packets: return False
+        if self.tx_packets != other.tx_packets: return False
+        if self.rx_bytes != other.rx_bytes: return False
+        if self.tx_bytes != other.tx_bytes: return False
+        if self.rx_dropped != other.rx_dropped: return False
+        if self.tx_dropped != other.tx_dropped: return False
+        if self.rx_errors != other.rx_errors: return False
+        if self.tx_errors != other.tx_errors: return False
+        if self.rx_frame_err != other.rx_frame_err: return False
+        if self.rx_over_err != other.rx_over_err: return False
+        if self.rx_crc_err != other.rx_crc_err: return False
+        if self.collisions != other.collisions: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("port_stats_entry {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("port_no = ");
+                q.text(util.pretty_port(self.port_no))
+                q.text(","); q.breakable()
+                q.text("rx_packets = ");
+                q.text("%#x" % self.rx_packets)
+                q.text(","); q.breakable()
+                q.text("tx_packets = ");
+                q.text("%#x" % self.tx_packets)
+                q.text(","); q.breakable()
+                q.text("rx_bytes = ");
+                q.text("%#x" % self.rx_bytes)
+                q.text(","); q.breakable()
+                q.text("tx_bytes = ");
+                q.text("%#x" % self.tx_bytes)
+                q.text(","); q.breakable()
+                q.text("rx_dropped = ");
+                q.text("%#x" % self.rx_dropped)
+                q.text(","); q.breakable()
+                q.text("tx_dropped = ");
+                q.text("%#x" % self.tx_dropped)
+                q.text(","); q.breakable()
+                q.text("rx_errors = ");
+                q.text("%#x" % self.rx_errors)
+                q.text(","); q.breakable()
+                q.text("tx_errors = ");
+                q.text("%#x" % self.tx_errors)
+                q.text(","); q.breakable()
+                q.text("rx_frame_err = ");
+                q.text("%#x" % self.rx_frame_err)
+                q.text(","); q.breakable()
+                q.text("rx_over_err = ");
+                q.text("%#x" % self.rx_over_err)
+                q.text(","); q.breakable()
+                q.text("rx_crc_err = ");
+                q.text("%#x" % self.rx_crc_err)
+                q.text(","); q.breakable()
+                q.text("collisions = ");
+                q.text("%#x" % self.collisions)
+            q.breakable()
+        q.text('}')
+
+class queue_prop_experimenter(object):
+    type = const.OFPQT_EXPERIMENTER
+
+    def __init__(self, experimenter=None, data=None):
+        if experimenter != None:
+            self.experimenter = experimenter
+        else:
+            self.experimenter = 0
+        if data != None:
+            self.data = data
+        else:
+            self.data = ""
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append('\x00' * 4)
+        packed.append(self.data)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = queue_prop_experimenter()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPQT_EXPERIMENTER)
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        obj.experimenter = reader.read('!L')[0]
+        reader.skip(4)
+        obj.data = str(reader.read_all())
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.experimenter != other.experimenter: return False
+        if self.data != other.data: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("queue_prop_experimenter {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("experimenter = ");
+                q.text("%#x" % self.experimenter)
+                q.text(","); q.breakable()
+                q.text("data = ");
+                q.pp(self.data)
+            q.breakable()
+        q.text('}')
+
+class queue_prop_max_rate(object):
+    type = const.OFPQT_MAX_RATE
+
+    def __init__(self, rate=None):
+        if rate != None:
+            self.rate = rate
+        else:
+            self.rate = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!H", self.rate))
+        packed.append('\x00' * 6)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = queue_prop_max_rate()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPQT_MAX_RATE)
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        obj.rate = reader.read('!H')[0]
+        reader.skip(6)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.rate != other.rate: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("queue_prop_max_rate {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("rate = ");
+                q.text("%#x" % self.rate)
+            q.breakable()
+        q.text('}')
+
+class queue_prop_min_rate(object):
+    type = const.OFPQT_MIN_RATE
+
+    def __init__(self, rate=None):
+        if rate != None:
+            self.rate = rate
+        else:
+            self.rate = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!H", self.rate))
+        packed.append('\x00' * 6)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = queue_prop_min_rate()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPQT_MIN_RATE)
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        obj.rate = reader.read('!H')[0]
+        reader.skip(6)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.rate != other.rate: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("queue_prop_min_rate {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("rate = ");
+                q.text("%#x" % self.rate)
+            q.breakable()
+        q.text('}')
+
+class queue_stats_entry(object):
+
+    def __init__(self, port_no=None, queue_id=None, tx_bytes=None, tx_packets=None, tx_errors=None):
+        if port_no != None:
+            self.port_no = port_no
+        else:
+            self.port_no = 0
+        if queue_id != None:
+            self.queue_id = queue_id
+        else:
+            self.queue_id = 0
+        if tx_bytes != None:
+            self.tx_bytes = tx_bytes
+        else:
+            self.tx_bytes = 0
+        if tx_packets != None:
+            self.tx_packets = tx_packets
+        else:
+            self.tx_packets = 0
+        if tx_errors != None:
+            self.tx_errors = tx_errors
+        else:
+            self.tx_errors = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.port_no))
+        packed.append(struct.pack("!L", self.queue_id))
+        packed.append(struct.pack("!Q", self.tx_bytes))
+        packed.append(struct.pack("!Q", self.tx_packets))
+        packed.append(struct.pack("!Q", self.tx_errors))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = queue_stats_entry()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.port_no = reader.read('!L')[0]
+        obj.queue_id = reader.read('!L')[0]
+        obj.tx_bytes = reader.read('!Q')[0]
+        obj.tx_packets = reader.read('!Q')[0]
+        obj.tx_errors = reader.read('!Q')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.port_no != other.port_no: return False
+        if self.queue_id != other.queue_id: return False
+        if self.tx_bytes != other.tx_bytes: return False
+        if self.tx_packets != other.tx_packets: return False
+        if self.tx_errors != other.tx_errors: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("queue_stats_entry {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("port_no = ");
+                q.text(util.pretty_port(self.port_no))
+                q.text(","); q.breakable()
+                q.text("queue_id = ");
+                q.text("%#x" % self.queue_id)
+                q.text(","); q.breakable()
+                q.text("tx_bytes = ");
+                q.text("%#x" % self.tx_bytes)
+                q.text(","); q.breakable()
+                q.text("tx_packets = ");
+                q.text("%#x" % self.tx_packets)
+                q.text(","); q.breakable()
+                q.text("tx_errors = ");
+                q.text("%#x" % self.tx_errors)
+            q.breakable()
+        q.text('}')
+
+class table_stats_entry(object):
+
+    def __init__(self, table_id=None, name=None, match=None, wildcards=None, write_actions=None, apply_actions=None, write_setfields=None, apply_setfields=None, metadata_match=None, metadata_write=None, instructions=None, config=None, max_entries=None, active_count=None, lookup_count=None, matched_count=None):
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if name != None:
+            self.name = name
+        else:
+            self.name = ""
+        if match != None:
+            self.match = match
+        else:
+            self.match = 0
+        if wildcards != None:
+            self.wildcards = wildcards
+        else:
+            self.wildcards = 0
+        if write_actions != None:
+            self.write_actions = write_actions
+        else:
+            self.write_actions = 0
+        if apply_actions != None:
+            self.apply_actions = apply_actions
+        else:
+            self.apply_actions = 0
+        if write_setfields != None:
+            self.write_setfields = write_setfields
+        else:
+            self.write_setfields = 0
+        if apply_setfields != None:
+            self.apply_setfields = apply_setfields
+        else:
+            self.apply_setfields = 0
+        if metadata_match != None:
+            self.metadata_match = metadata_match
+        else:
+            self.metadata_match = 0
+        if metadata_write != None:
+            self.metadata_write = metadata_write
+        else:
+            self.metadata_write = 0
+        if instructions != None:
+            self.instructions = instructions
+        else:
+            self.instructions = 0
+        if config != None:
+            self.config = config
+        else:
+            self.config = 0
+        if max_entries != None:
+            self.max_entries = max_entries
+        else:
+            self.max_entries = 0
+        if active_count != None:
+            self.active_count = active_count
+        else:
+            self.active_count = 0
+        if lookup_count != None:
+            self.lookup_count = lookup_count
+        else:
+            self.lookup_count = 0
+        if matched_count != None:
+            self.matched_count = matched_count
+        else:
+            self.matched_count = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append('\x00' * 7)
+        packed.append(struct.pack("!32s", self.name))
+        packed.append(struct.pack("!Q", self.match))
+        packed.append(struct.pack("!Q", self.wildcards))
+        packed.append(struct.pack("!L", self.write_actions))
+        packed.append(struct.pack("!L", self.apply_actions))
+        packed.append(struct.pack("!Q", self.write_setfields))
+        packed.append(struct.pack("!Q", self.apply_setfields))
+        packed.append(struct.pack("!Q", self.metadata_match))
+        packed.append(struct.pack("!Q", self.metadata_write))
+        packed.append(struct.pack("!L", self.instructions))
+        packed.append(struct.pack("!L", self.config))
+        packed.append(struct.pack("!L", self.max_entries))
+        packed.append(struct.pack("!L", self.active_count))
+        packed.append(struct.pack("!Q", self.lookup_count))
+        packed.append(struct.pack("!Q", self.matched_count))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = table_stats_entry()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.table_id = reader.read('!B')[0]
+        reader.skip(7)
+        obj.name = reader.read("!32s")[0].rstrip("\x00")
+        obj.match = reader.read('!Q')[0]
+        obj.wildcards = reader.read('!Q')[0]
+        obj.write_actions = reader.read('!L')[0]
+        obj.apply_actions = reader.read('!L')[0]
+        obj.write_setfields = reader.read('!Q')[0]
+        obj.apply_setfields = reader.read('!Q')[0]
+        obj.metadata_match = reader.read('!Q')[0]
+        obj.metadata_write = reader.read('!Q')[0]
+        obj.instructions = reader.read('!L')[0]
+        obj.config = reader.read('!L')[0]
+        obj.max_entries = reader.read('!L')[0]
+        obj.active_count = reader.read('!L')[0]
+        obj.lookup_count = reader.read('!Q')[0]
+        obj.matched_count = reader.read('!Q')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.table_id != other.table_id: return False
+        if self.name != other.name: return False
+        if self.match != other.match: return False
+        if self.wildcards != other.wildcards: return False
+        if self.write_actions != other.write_actions: return False
+        if self.apply_actions != other.apply_actions: return False
+        if self.write_setfields != other.write_setfields: return False
+        if self.apply_setfields != other.apply_setfields: return False
+        if self.metadata_match != other.metadata_match: return False
+        if self.metadata_write != other.metadata_write: return False
+        if self.instructions != other.instructions: return False
+        if self.config != other.config: return False
+        if self.max_entries != other.max_entries: return False
+        if self.active_count != other.active_count: return False
+        if self.lookup_count != other.lookup_count: return False
+        if self.matched_count != other.matched_count: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_stats_entry {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("name = ");
+                q.pp(self.name)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+                q.text(","); q.breakable()
+                q.text("wildcards = ");
+                q.pp(self.wildcards)
+                q.text(","); q.breakable()
+                q.text("write_actions = ");
+                q.text("%#x" % self.write_actions)
+                q.text(","); q.breakable()
+                q.text("apply_actions = ");
+                q.text("%#x" % self.apply_actions)
+                q.text(","); q.breakable()
+                q.text("write_setfields = ");
+                q.text("%#x" % self.write_setfields)
+                q.text(","); q.breakable()
+                q.text("apply_setfields = ");
+                q.text("%#x" % self.apply_setfields)
+                q.text(","); q.breakable()
+                q.text("metadata_match = ");
+                q.text("%#x" % self.metadata_match)
+                q.text(","); q.breakable()
+                q.text("metadata_write = ");
+                q.text("%#x" % self.metadata_write)
+                q.text(","); q.breakable()
+                q.text("instructions = ");
+                q.text("%#x" % self.instructions)
+                q.text(","); q.breakable()
+                q.text("config = ");
+                q.text("%#x" % self.config)
+                q.text(","); q.breakable()
+                q.text("max_entries = ");
+                q.text("%#x" % self.max_entries)
+                q.text(","); q.breakable()
+                q.text("active_count = ");
+                q.text("%#x" % self.active_count)
+                q.text(","); q.breakable()
+                q.text("lookup_count = ");
+                q.text("%#x" % self.lookup_count)
+                q.text(","); q.breakable()
+                q.text("matched_count = ");
+                q.text("%#x" % self.matched_count)
+            q.breakable()
+        q.text('}')
+
+
+match = match_v3
diff --git a/src/python/loxi/of12/const.py b/src/python/loxi/of12/const.py
new file mode 100644
index 0000000..fa9c93c
--- /dev/null
+++ b/src/python/loxi/of12/const.py
@@ -0,0 +1,760 @@
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+
+# Automatically generated by LOXI from template const.py
+# Do not modify
+
+OFP_VERSION = 3
+
+# Identifiers from group macro_definitions
+OFP_VLAN_NONE = 0
+OFP_FLOW_PERMANENT = 0
+OFP_ETH_ALEN = 6
+OFP_MAX_PORT_NAME_LEN = 16
+OFP_MAX_TABLE_NAME_LEN = 32
+SERIAL_NUM_LEN = 32
+OFP_DEFAULT_MISS_SEND_LEN = 128
+DESC_STR_LEN = 256
+OFP_TCP_PORT = 6633
+OFP_SSL_PORT = 6633
+OFP_DEFAULT_PRIORITY = 32768
+OFPQ_MIN_RATE_UNCFG = 65535
+OFPQ_MAX_RATE_UNCFG = 65535
+OFPQ_ALL = 4294967295
+OFP_NO_BUFFER = 4294967295
+
+# Identifiers from group ofp_action_type
+OFPAT_OUTPUT = 0
+OFPAT_COPY_TTL_OUT = 11
+OFPAT_COPY_TTL_IN = 12
+OFPAT_SET_MPLS_TTL = 15
+OFPAT_DEC_MPLS_TTL = 16
+OFPAT_PUSH_VLAN = 17
+OFPAT_POP_VLAN = 18
+OFPAT_PUSH_MPLS = 19
+OFPAT_POP_MPLS = 20
+OFPAT_SET_QUEUE = 21
+OFPAT_GROUP = 22
+OFPAT_SET_NW_TTL = 23
+OFPAT_DEC_NW_TTL = 24
+OFPAT_SET_FIELD = 25
+OFPAT_EXPERIMENTER = 65535
+
+ofp_action_type_map = {
+    0: 'OFPAT_OUTPUT',
+    11: 'OFPAT_COPY_TTL_OUT',
+    12: 'OFPAT_COPY_TTL_IN',
+    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',
+    65535: 'OFPAT_EXPERIMENTER',
+}
+
+# Identifiers from group ofp_bad_action_code
+OFPBAC_BAD_TYPE = 0
+OFPBAC_BAD_LEN = 1
+OFPBAC_BAD_EXPERIMENTER = 2
+OFPBAC_BAD_EXP_TYPE = 3
+OFPBAC_BAD_OUT_PORT = 4
+OFPBAC_BAD_ARGUMENT = 5
+OFPBAC_EPERM = 6
+OFPBAC_TOO_MANY = 7
+OFPBAC_BAD_QUEUE = 8
+OFPBAC_BAD_OUT_GROUP = 9
+OFPBAC_MATCH_INCONSISTENT = 10
+OFPBAC_UNSUPPORTED_ORDER = 11
+OFPBAC_BAD_TAG = 12
+OFPBAC_BAD_SET_TYPE = 13
+OFPBAC_BAD_SET_LEN = 14
+OFPBAC_BAD_SET_ARGUMENT = 15
+
+ofp_bad_action_code_map = {
+    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',
+}
+
+# Identifiers from group ofp_bad_instruction_code
+OFPBIC_UNKNOWN_INST = 0
+OFPBIC_UNSUP_INST = 1
+OFPBIC_BAD_TABLE_ID = 2
+OFPBIC_UNSUP_METADATA = 3
+OFPBIC_UNSUP_METADATA_MASK = 4
+OFPBIC_BAD_EXPERIMENTER = 5
+OFPBIC_BAD_EXP_TYPE = 6
+OFPBIC_BAD_LEN = 7
+OFPBIC_EPERM = 8
+
+ofp_bad_instruction_code_map = {
+    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',
+}
+
+# Identifiers from group ofp_bad_match_code
+OFPBMC_BAD_TYPE = 0
+OFPBMC_BAD_LEN = 1
+OFPBMC_BAD_TAG = 2
+OFPBMC_BAD_DL_ADDR_MASK = 3
+OFPBMC_BAD_NW_ADDR_MASK = 4
+OFPBMC_BAD_WILDCARDS = 5
+OFPBMC_BAD_FIELD = 6
+OFPBMC_BAD_VALUE = 7
+OFPBMC_BAD_MASK = 8
+OFPBMC_BAD_PREREQ = 9
+OFPBMC_DUP_FIELD = 10
+OFPBMC_EPERM = 11
+
+ofp_bad_match_code_map = {
+    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',
+}
+
+# Identifiers from group ofp_bad_request_code
+OFPBRC_BAD_VERSION = 0
+OFPBRC_BAD_TYPE = 1
+OFPBRC_BAD_STAT = 2
+OFPBRC_BAD_EXPERIMENTER = 3
+OFPBRC_BAD_EXP_TYPE = 4
+OFPBRC_EPERM = 5
+OFPBRC_BAD_LEN = 6
+OFPBRC_BUFFER_EMPTY = 7
+OFPBRC_BUFFER_UNKNOWN = 8
+OFPBRC_BAD_TABLE_ID = 9
+OFPBRC_IS_SLAVE = 10
+OFPBRC_BAD_PORT = 11
+OFPBRC_BAD_PACKET = 12
+
+ofp_bad_request_code_map = {
+    0: 'OFPBRC_BAD_VERSION',
+    1: 'OFPBRC_BAD_TYPE',
+    2: 'OFPBRC_BAD_STAT',
+    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',
+}
+
+# Identifiers from group ofp_capabilities
+OFPC_FLOW_STATS = 1
+OFPC_TABLE_STATS = 2
+OFPC_PORT_STATS = 4
+OFPC_GROUP_STATS = 8
+OFPC_IP_REASM = 32
+OFPC_QUEUE_STATS = 64
+OFPC_PORT_BLOCKED = 256
+
+ofp_capabilities_map = {
+    1: 'OFPC_FLOW_STATS',
+    2: 'OFPC_TABLE_STATS',
+    4: 'OFPC_PORT_STATS',
+    8: 'OFPC_GROUP_STATS',
+    32: 'OFPC_IP_REASM',
+    64: 'OFPC_QUEUE_STATS',
+    256: 'OFPC_PORT_BLOCKED',
+}
+
+# Identifiers from group ofp_config_flags
+OFPC_FRAG_NORMAL = 0
+OFPC_FRAG_DROP = 1
+OFPC_FRAG_REASM = 2
+OFPC_FRAG_MASK = 3
+OFPC_INVALID_TTL_TO_CONTROLLER = 4
+
+ofp_config_flags_map = {
+    0: 'OFPC_FRAG_NORMAL',
+    1: 'OFPC_FRAG_DROP',
+    2: 'OFPC_FRAG_REASM',
+    3: 'OFPC_FRAG_MASK',
+    4: 'OFPC_INVALID_TTL_TO_CONTROLLER',
+}
+
+# Identifiers from group ofp_controller_max_len
+OFPCML_MAX = 65509
+OFPCML_NO_BUFFER = 65535
+
+ofp_controller_max_len_map = {
+    65509: 'OFPCML_MAX',
+    65535: 'OFPCML_NO_BUFFER',
+}
+
+# Identifiers from group ofp_controller_role
+OFPCR_ROLE_NOCHANGE = 0
+OFPCR_ROLE_EQUAL = 1
+OFPCR_ROLE_MASTER = 2
+OFPCR_ROLE_SLAVE = 3
+
+ofp_controller_role_map = {
+    0: 'OFPCR_ROLE_NOCHANGE',
+    1: 'OFPCR_ROLE_EQUAL',
+    2: 'OFPCR_ROLE_MASTER',
+    3: 'OFPCR_ROLE_SLAVE',
+}
+
+# Identifiers from group ofp_error_type
+OFPET_HELLO_FAILED = 0
+OFPET_BAD_REQUEST = 1
+OFPET_BAD_ACTION = 2
+OFPET_BAD_INSTRUCTION = 3
+OFPET_BAD_MATCH = 4
+OFPET_FLOW_MOD_FAILED = 5
+OFPET_GROUP_MOD_FAILED = 6
+OFPET_PORT_MOD_FAILED = 7
+OFPET_TABLE_MOD_FAILED = 8
+OFPET_QUEUE_OP_FAILED = 9
+OFPET_SWITCH_CONFIG_FAILED = 10
+OFPET_ROLE_REQUEST_FAILED = 11
+OFPET_EXPERIMENTER = 65535
+
+ofp_error_type_map = {
+    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',
+    65535: 'OFPET_EXPERIMENTER',
+}
+
+# Identifiers from group ofp_flow_mod_command
+OFPFC_ADD = 0
+OFPFC_MODIFY = 1
+OFPFC_MODIFY_STRICT = 2
+OFPFC_DELETE = 3
+OFPFC_DELETE_STRICT = 4
+
+ofp_flow_mod_command_map = {
+    0: 'OFPFC_ADD',
+    1: 'OFPFC_MODIFY',
+    2: 'OFPFC_MODIFY_STRICT',
+    3: 'OFPFC_DELETE',
+    4: 'OFPFC_DELETE_STRICT',
+}
+
+# Identifiers from group ofp_flow_mod_failed_code
+OFPFMFC_UNKNOWN = 0
+OFPFMFC_TABLE_FULL = 1
+OFPFMFC_BAD_TABLE_ID = 2
+OFPFMFC_OVERLAP = 3
+OFPFMFC_EPERM = 4
+OFPFMFC_BAD_TIMEOUT = 5
+OFPFMFC_BAD_COMMAND = 6
+OFPFMFC_BAD_FLAGS = 7
+
+ofp_flow_mod_failed_code_map = {
+    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',
+}
+
+# Identifiers from group ofp_flow_mod_flags
+OFPFF_SEND_FLOW_REM = 1
+OFPFF_CHECK_OVERLAP = 2
+OFPFF_RESET_COUNTS = 4
+
+ofp_flow_mod_flags_map = {
+    1: 'OFPFF_SEND_FLOW_REM',
+    2: 'OFPFF_CHECK_OVERLAP',
+    4: 'OFPFF_RESET_COUNTS',
+}
+
+# Identifiers from group ofp_flow_removed_reason
+OFPRR_IDLE_TIMEOUT = 0
+OFPRR_HARD_TIMEOUT = 1
+OFPRR_DELETE = 2
+OFPRR_GROUP_DELETE = 3
+
+ofp_flow_removed_reason_map = {
+    0: 'OFPRR_IDLE_TIMEOUT',
+    1: 'OFPRR_HARD_TIMEOUT',
+    2: 'OFPRR_DELETE',
+    3: 'OFPRR_GROUP_DELETE',
+}
+
+# Identifiers from group ofp_group
+OFPG_MAX = 4294967040
+OFPG_ALL = 4294967292
+OFPG_ANY = 4294967295
+
+ofp_group_map = {
+    4294967040: 'OFPG_MAX',
+    4294967292: 'OFPG_ALL',
+    4294967295: 'OFPG_ANY',
+}
+
+# Identifiers from group ofp_group_capabilities
+OFPGFC_SELECT_WEIGHT = 1
+OFPGFC_SELECT_LIVENESS = 2
+OFPGFC_CHAINING = 4
+OFPGFC_CHAINING_CHECKS = 8
+
+ofp_group_capabilities_map = {
+    1: 'OFPGFC_SELECT_WEIGHT',
+    2: 'OFPGFC_SELECT_LIVENESS',
+    4: 'OFPGFC_CHAINING',
+    8: 'OFPGFC_CHAINING_CHECKS',
+}
+
+# Identifiers from group ofp_group_mod_command
+OFPGC_ADD = 0
+OFPGC_MODIFY = 1
+OFPGC_DELETE = 2
+
+ofp_group_mod_command_map = {
+    0: 'OFPGC_ADD',
+    1: 'OFPGC_MODIFY',
+    2: 'OFPGC_DELETE',
+}
+
+# Identifiers from group ofp_group_mod_failed_code
+OFPGMFC_GROUP_EXISTS = 0
+OFPGMFC_INVALID_GROUP = 1
+OFPGMFC_WEIGHT_UNSUPPORTED = 2
+OFPGMFC_OUT_OF_GROUPS = 3
+OFPGMFC_OUT_OF_BUCKETS = 4
+OFPGMFC_CHAINING_UNSUPPORTED = 5
+OFPGMFC_WATCH_UNSUPPORTED = 6
+OFPGMFC_LOOP = 7
+OFPGMFC_UNKNOWN_GROUP = 8
+OFPGMFC_CHAINED_GROUP = 9
+OFPGMFC_BAD_TYPE = 10
+OFPGMFC_BAD_COMMAND = 11
+OFPGMFC_BAD_BUCKET = 12
+OFPGMFC_BAD_WATCH = 13
+OFPGMFC_EPERM = 14
+
+ofp_group_mod_failed_code_map = {
+    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: 'OFPGMFC_EPERM',
+}
+
+# Identifiers from group ofp_group_type
+OFPGT_ALL = 0
+OFPGT_SELECT = 1
+OFPGT_INDIRECT = 2
+OFPGT_FF = 3
+
+ofp_group_type_map = {
+    0: 'OFPGT_ALL',
+    1: 'OFPGT_SELECT',
+    2: 'OFPGT_INDIRECT',
+    3: 'OFPGT_FF',
+}
+
+# Identifiers from group ofp_hello_failed_code
+OFPHFC_INCOMPATIBLE = 0
+OFPHFC_EPERM = 1
+
+ofp_hello_failed_code_map = {
+    0: 'OFPHFC_INCOMPATIBLE',
+    1: 'OFPHFC_EPERM',
+}
+
+# Identifiers from group ofp_instruction_type
+OFPIT_GOTO_TABLE = 1
+OFPIT_WRITE_METADATA = 2
+OFPIT_WRITE_ACTIONS = 3
+OFPIT_APPLY_ACTIONS = 4
+OFPIT_CLEAR_ACTIONS = 5
+OFPIT_EXPERIMENTER = 65535
+
+ofp_instruction_type_map = {
+    1: 'OFPIT_GOTO_TABLE',
+    2: 'OFPIT_WRITE_METADATA',
+    3: 'OFPIT_WRITE_ACTIONS',
+    4: 'OFPIT_APPLY_ACTIONS',
+    5: 'OFPIT_CLEAR_ACTIONS',
+    65535: 'OFPIT_EXPERIMENTER',
+}
+
+# Identifiers from group ofp_match_type
+OFPMT_STANDARD = 0
+OFPMT_OXM = 1
+
+ofp_match_type_map = {
+    0: 'OFPMT_STANDARD',
+    1: 'OFPMT_OXM',
+}
+
+# Identifiers from group ofp_oxm_class
+OFPXMC_NXM_0 = 0
+OFPXMC_NXM_1 = 1
+OFPXMC_OPENFLOW_BASIC = 32768
+OFPXMC_EXPERIMENTER = 65535
+
+ofp_oxm_class_map = {
+    0: 'OFPXMC_NXM_0',
+    1: 'OFPXMC_NXM_1',
+    32768: 'OFPXMC_OPENFLOW_BASIC',
+    65535: 'OFPXMC_EXPERIMENTER',
+}
+
+# Identifiers from group ofp_packet_in_reason
+OFPR_NO_MATCH = 0
+OFPR_ACTION = 1
+OFPR_INVALID_TTL = 2
+
+ofp_packet_in_reason_map = {
+    0: 'OFPR_NO_MATCH',
+    1: 'OFPR_ACTION',
+    2: 'OFPR_INVALID_TTL',
+}
+
+# Identifiers from group ofp_port
+OFPP_MAX = 4294967040
+OFPP_IN_PORT = 4294967288
+OFPP_TABLE = 4294967289
+OFPP_NORMAL = 4294967290
+OFPP_FLOOD = 4294967291
+OFPP_ALL = 4294967292
+OFPP_CONTROLLER = 4294967293
+OFPP_LOCAL = 4294967294
+
+ofp_port_map = {
+    4294967040: 'OFPP_MAX',
+    4294967288: 'OFPP_IN_PORT',
+    4294967289: 'OFPP_TABLE',
+    4294967290: 'OFPP_NORMAL',
+    4294967291: 'OFPP_FLOOD',
+    4294967292: 'OFPP_ALL',
+    4294967293: 'OFPP_CONTROLLER',
+    4294967294: 'OFPP_LOCAL',
+}
+
+# Identifiers from group ofp_port_config
+OFPPC_PORT_DOWN = 1
+OFPPC_NO_RECV = 4
+OFPPC_NO_FWD = 32
+OFPPC_NO_PACKET_IN = 64
+
+ofp_port_config_map = {
+    1: 'OFPPC_PORT_DOWN',
+    4: 'OFPPC_NO_RECV',
+    32: 'OFPPC_NO_FWD',
+    64: 'OFPPC_NO_PACKET_IN',
+}
+
+# Identifiers from group ofp_port_features
+OFPPF_10MB_HD = 1
+OFPPF_10MB_FD = 2
+OFPPF_100MB_HD = 4
+OFPPF_100MB_FD = 8
+OFPPF_1GB_HD = 16
+OFPPF_1GB_FD = 32
+OFPPF_10GB_FD = 64
+OFPPF_40GB_FD = 128
+OFPPF_100GB_FD = 256
+OFPPF_1TB_FD = 512
+OFPPF_OTHER = 1024
+OFPPF_COPPER = 2048
+OFPPF_FIBER = 4096
+OFPPF_AUTONEG = 8192
+OFPPF_PAUSE = 16384
+OFPPF_PAUSE_ASYM = 32768
+
+ofp_port_features_map = {
+    1: 'OFPPF_10MB_HD',
+    2: 'OFPPF_10MB_FD',
+    4: 'OFPPF_100MB_HD',
+    8: 'OFPPF_100MB_FD',
+    16: 'OFPPF_1GB_HD',
+    32: 'OFPPF_1GB_FD',
+    64: 'OFPPF_10GB_FD',
+    128: 'OFPPF_40GB_FD',
+    256: 'OFPPF_100GB_FD',
+    512: 'OFPPF_1TB_FD',
+    1024: 'OFPPF_OTHER',
+    2048: 'OFPPF_COPPER',
+    4096: 'OFPPF_FIBER',
+    8192: 'OFPPF_AUTONEG',
+    16384: 'OFPPF_PAUSE',
+    32768: 'OFPPF_PAUSE_ASYM',
+}
+
+# Identifiers from group ofp_port_mod_failed_code
+OFPPMFC_BAD_PORT = 0
+OFPPMFC_BAD_HW_ADDR = 1
+OFPPMFC_BAD_CONFIG = 2
+OFPPMFC_BAD_ADVERTISE = 3
+OFPPMFC_EPERM = 4
+
+ofp_port_mod_failed_code_map = {
+    0: 'OFPPMFC_BAD_PORT',
+    1: 'OFPPMFC_BAD_HW_ADDR',
+    2: 'OFPPMFC_BAD_CONFIG',
+    3: 'OFPPMFC_BAD_ADVERTISE',
+    4: 'OFPPMFC_EPERM',
+}
+
+# Identifiers from group ofp_port_no
+OFPP_ANY = 4294967295
+
+ofp_port_no_map = {
+    4294967295: 'OFPP_ANY',
+}
+
+# Identifiers from group ofp_port_reason
+OFPPR_ADD = 0
+OFPPR_DELETE = 1
+OFPPR_MODIFY = 2
+
+ofp_port_reason_map = {
+    0: 'OFPPR_ADD',
+    1: 'OFPPR_DELETE',
+    2: 'OFPPR_MODIFY',
+}
+
+# Identifiers from group ofp_port_state
+OFPPS_LINK_DOWN = 1
+OFPPS_BLOCKED = 2
+OFPPS_LIVE = 4
+
+ofp_port_state_map = {
+    1: 'OFPPS_LINK_DOWN',
+    2: 'OFPPS_BLOCKED',
+    4: 'OFPPS_LIVE',
+}
+
+# Identifiers from group ofp_queue_op_failed_code
+OFPQOFC_BAD_PORT = 0
+OFPQOFC_BAD_QUEUE = 1
+OFPQOFC_EPERM = 2
+
+ofp_queue_op_failed_code_map = {
+    0: 'OFPQOFC_BAD_PORT',
+    1: 'OFPQOFC_BAD_QUEUE',
+    2: 'OFPQOFC_EPERM',
+}
+
+# Identifiers from group ofp_queue_properties
+OFPQT_MIN_RATE = 1
+OFPQT_MAX_RATE = 2
+OFPQT_EXPERIMENTER = 65535
+
+ofp_queue_properties_map = {
+    1: 'OFPQT_MIN_RATE',
+    2: 'OFPQT_MAX_RATE',
+    65535: 'OFPQT_EXPERIMENTER',
+}
+
+# Identifiers from group ofp_role_request_failed_code
+OFPRRFC_STALE = 0
+OFPRRFC_UNSUP = 1
+OFPRRFC_BAD_ROLE = 2
+
+ofp_role_request_failed_code_map = {
+    0: 'OFPRRFC_STALE',
+    1: 'OFPRRFC_UNSUP',
+    2: 'OFPRRFC_BAD_ROLE',
+}
+
+# Identifiers from group ofp_stats_reply_flags
+OFPSF_REPLY_MORE = 1
+
+ofp_stats_reply_flags_map = {
+    1: 'OFPSF_REPLY_MORE',
+}
+
+# Identifiers from group ofp_stats_types
+OFPST_DESC = 0
+OFPST_FLOW = 1
+OFPST_AGGREGATE = 2
+OFPST_TABLE = 3
+OFPST_PORT = 4
+OFPST_QUEUE = 5
+OFPST_GROUP = 6
+OFPST_GROUP_DESC = 7
+OFPST_GROUP_FEATURES = 8
+OFPST_EXPERIMENTER = 65535
+
+ofp_stats_types_map = {
+    0: 'OFPST_DESC',
+    1: 'OFPST_FLOW',
+    2: 'OFPST_AGGREGATE',
+    3: 'OFPST_TABLE',
+    4: 'OFPST_PORT',
+    5: 'OFPST_QUEUE',
+    6: 'OFPST_GROUP',
+    7: 'OFPST_GROUP_DESC',
+    8: 'OFPST_GROUP_FEATURES',
+    65535: 'OFPST_EXPERIMENTER',
+}
+
+# Identifiers from group ofp_switch_config_failed_code
+OFPSCFC_BAD_FLAGS = 0
+OFPSCFC_BAD_LEN = 1
+OFPSCFC_EPERM = 2
+
+ofp_switch_config_failed_code_map = {
+    0: 'OFPSCFC_BAD_FLAGS',
+    1: 'OFPSCFC_BAD_LEN',
+    2: 'OFPSCFC_EPERM',
+}
+
+# Identifiers from group ofp_table
+OFPTT_MAX = 254
+OFPTT_ALL = 255
+
+ofp_table_map = {
+    254: 'OFPTT_MAX',
+    255: 'OFPTT_ALL',
+}
+
+# Identifiers from group ofp_table_config
+OFPTC_TABLE_MISS_CONTROLLER = 0
+OFPTC_TABLE_MISS_CONTINUE = 1
+OFPTC_TABLE_MISS_DROP = 2
+OFPTC_TABLE_MISS_MASK = 3
+
+ofp_table_config_map = {
+    0: 'OFPTC_TABLE_MISS_CONTROLLER',
+    1: 'OFPTC_TABLE_MISS_CONTINUE',
+    2: 'OFPTC_TABLE_MISS_DROP',
+    3: 'OFPTC_TABLE_MISS_MASK',
+}
+
+# Identifiers from group ofp_table_mod_failed_code
+OFPTMFC_BAD_TABLE = 0
+OFPTMFC_BAD_CONFIG = 1
+OFPTMFC_EPERM = 2
+
+ofp_table_mod_failed_code_map = {
+    0: 'OFPTMFC_BAD_TABLE',
+    1: 'OFPTMFC_BAD_CONFIG',
+    2: 'OFPTMFC_EPERM',
+}
+
+# Identifiers from group ofp_type
+OFPT_HELLO = 0
+OFPT_ERROR = 1
+OFPT_ECHO_REQUEST = 2
+OFPT_ECHO_REPLY = 3
+OFPT_EXPERIMENTER = 4
+OFPT_FEATURES_REQUEST = 5
+OFPT_FEATURES_REPLY = 6
+OFPT_GET_CONFIG_REQUEST = 7
+OFPT_GET_CONFIG_REPLY = 8
+OFPT_SET_CONFIG = 9
+OFPT_PACKET_IN = 10
+OFPT_FLOW_REMOVED = 11
+OFPT_PORT_STATUS = 12
+OFPT_PACKET_OUT = 13
+OFPT_FLOW_MOD = 14
+OFPT_GROUP_MOD = 15
+OFPT_PORT_MOD = 16
+OFPT_TABLE_MOD = 17
+OFPT_STATS_REQUEST = 18
+OFPT_STATS_REPLY = 19
+OFPT_BARRIER_REQUEST = 20
+OFPT_BARRIER_REPLY = 21
+OFPT_QUEUE_GET_CONFIG_REQUEST = 22
+OFPT_QUEUE_GET_CONFIG_REPLY = 23
+OFPT_ROLE_REQUEST = 24
+OFPT_ROLE_REPLY = 25
+
+ofp_type_map = {
+    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_STATS_REQUEST',
+    19: 'OFPT_STATS_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',
+}
+
+# Identifiers from group ofp_vlan_id
+OFPVID_NONE = 0
+OFPVID_PRESENT = 4096
+
+ofp_vlan_id_map = {
+    0: 'OFPVID_NONE',
+    4096: 'OFPVID_PRESENT',
+}
+
diff --git a/src/python/loxi/of12/message.py b/src/python/loxi/of12/message.py
new file mode 100644
index 0000000..61e90d4
--- /dev/null
+++ b/src/python/loxi/of12/message.py
@@ -0,0 +1,5627 @@
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+
+# Automatically generated by LOXI from template message.py
+# Do not modify
+
+import struct
+import loxi
+import const
+import common
+import action # for unpack_list
+import instruction # for unpack_list
+import util
+import loxi.generic_util
+
+class Message(object):
+    version = const.OFP_VERSION
+    type = None # override in subclass
+    xid = None
+
+class aggregate_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REPLY
+    stats_type = const.OFPST_AGGREGATE
+
+    def __init__(self, xid=None, flags=None, packet_count=None, byte_count=None, flow_count=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if packet_count != None:
+            self.packet_count = packet_count
+        else:
+            self.packet_count = 0
+        if byte_count != None:
+            self.byte_count = byte_count
+        else:
+            self.byte_count = 0
+        if flow_count != None:
+            self.flow_count = flow_count
+        else:
+            self.flow_count = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!Q", self.packet_count))
+        packed.append(struct.pack("!Q", self.byte_count))
+        packed.append(struct.pack("!L", self.flow_count))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = aggregate_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_AGGREGATE)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.packet_count = reader.read('!Q')[0]
+        obj.byte_count = reader.read('!Q')[0]
+        obj.flow_count = reader.read('!L')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.packet_count != other.packet_count: return False
+        if self.byte_count != other.byte_count: return False
+        if self.flow_count != other.flow_count: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("aggregate_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("packet_count = ");
+                q.text("%#x" % self.packet_count)
+                q.text(","); q.breakable()
+                q.text("byte_count = ");
+                q.text("%#x" % self.byte_count)
+                q.text(","); q.breakable()
+                q.text("flow_count = ");
+                q.text("%#x" % self.flow_count)
+            q.breakable()
+        q.text('}')
+
+class aggregate_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REQUEST
+    stats_type = const.OFPST_AGGREGATE
+
+    def __init__(self, xid=None, flags=None, table_id=None, out_port=None, out_group=None, cookie=None, cookie_mask=None, match=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if out_port != None:
+            self.out_port = out_port
+        else:
+            self.out_port = 0
+        if out_group != None:
+            self.out_group = out_group
+        else:
+            self.out_group = 0
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if cookie_mask != None:
+            self.cookie_mask = cookie_mask
+        else:
+            self.cookie_mask = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append('\x00' * 3)
+        packed.append(struct.pack("!L", self.out_port))
+        packed.append(struct.pack("!L", self.out_group))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!Q", self.cookie_mask))
+        packed.append(self.match.pack())
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = aggregate_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_AGGREGATE)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.table_id = reader.read('!B')[0]
+        reader.skip(3)
+        obj.out_port = reader.read('!L')[0]
+        obj.out_group = reader.read('!L')[0]
+        reader.skip(4)
+        obj.cookie = reader.read('!Q')[0]
+        obj.cookie_mask = reader.read('!Q')[0]
+        obj.match = common.match.unpack(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.table_id != other.table_id: return False
+        if self.out_port != other.out_port: return False
+        if self.out_group != other.out_group: return False
+        if self.cookie != other.cookie: return False
+        if self.cookie_mask != other.cookie_mask: return False
+        if self.match != other.match: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("aggregate_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("out_port = ");
+                q.text(util.pretty_port(self.out_port))
+                q.text(","); q.breakable()
+                q.text("out_group = ");
+                q.text("%#x" % self.out_group)
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("cookie_mask = ");
+                q.text("%#x" % self.cookie_mask)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+            q.breakable()
+        q.text('}')
+
+class barrier_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_BARRIER_REPLY
+
+    def __init__(self, xid=None):
+        self.xid = xid
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = barrier_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_BARRIER_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("barrier_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+            q.breakable()
+        q.text('}')
+
+class barrier_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_BARRIER_REQUEST
+
+    def __init__(self, xid=None):
+        self.xid = xid
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = barrier_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_BARRIER_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("barrier_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+            q.breakable()
+        q.text('}')
+
+class bsn_get_interfaces_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_EXPERIMENTER
+    experimenter = 0x5c16c7
+    subtype = 10
+
+    def __init__(self, xid=None, interfaces=None):
+        self.xid = xid
+        if interfaces != None:
+            self.interfaces = interfaces
+        else:
+            self.interfaces = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        packed.append("".join([x.pack() for x in self.interfaces]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = bsn_get_interfaces_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_EXPERIMENTER)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 10)
+        obj.interfaces = loxi.generic_util.unpack_list(reader, common.bsn_interface.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.interfaces != other.interfaces: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_get_interfaces_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("interfaces = ");
+                q.pp(self.interfaces)
+            q.breakable()
+        q.text('}')
+
+class bsn_get_interfaces_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_EXPERIMENTER
+    experimenter = 0x5c16c7
+    subtype = 9
+
+    def __init__(self, xid=None):
+        self.xid = xid
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = bsn_get_interfaces_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_EXPERIMENTER)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 9)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_get_interfaces_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+            q.breakable()
+        q.text('}')
+
+class bsn_get_mirroring_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_EXPERIMENTER
+    experimenter = 0x5c16c7
+    subtype = 5
+
+    def __init__(self, xid=None, report_mirror_ports=None):
+        self.xid = xid
+        if report_mirror_ports != None:
+            self.report_mirror_ports = report_mirror_ports
+        else:
+            self.report_mirror_ports = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        packed.append(struct.pack("!B", self.report_mirror_ports))
+        packed.append('\x00' * 3)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = bsn_get_mirroring_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_EXPERIMENTER)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 5)
+        obj.report_mirror_ports = reader.read('!B')[0]
+        reader.skip(3)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.report_mirror_ports != other.report_mirror_ports: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_get_mirroring_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("report_mirror_ports = ");
+                q.text("%#x" % self.report_mirror_ports)
+            q.breakable()
+        q.text('}')
+
+class bsn_get_mirroring_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_EXPERIMENTER
+    experimenter = 0x5c16c7
+    subtype = 4
+
+    def __init__(self, xid=None, report_mirror_ports=None):
+        self.xid = xid
+        if report_mirror_ports != None:
+            self.report_mirror_ports = report_mirror_ports
+        else:
+            self.report_mirror_ports = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        packed.append(struct.pack("!B", self.report_mirror_ports))
+        packed.append('\x00' * 3)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = bsn_get_mirroring_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_EXPERIMENTER)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 4)
+        obj.report_mirror_ports = reader.read('!B')[0]
+        reader.skip(3)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.report_mirror_ports != other.report_mirror_ports: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_get_mirroring_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("report_mirror_ports = ");
+                q.text("%#x" % self.report_mirror_ports)
+            q.breakable()
+        q.text('}')
+
+class bsn_set_mirroring(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_EXPERIMENTER
+    experimenter = 0x5c16c7
+    subtype = 3
+
+    def __init__(self, xid=None, report_mirror_ports=None):
+        self.xid = xid
+        if report_mirror_ports != None:
+            self.report_mirror_ports = report_mirror_ports
+        else:
+            self.report_mirror_ports = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        packed.append(struct.pack("!B", self.report_mirror_ports))
+        packed.append('\x00' * 3)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = bsn_set_mirroring()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_EXPERIMENTER)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 3)
+        obj.report_mirror_ports = reader.read('!B')[0]
+        reader.skip(3)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.report_mirror_ports != other.report_mirror_ports: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_set_mirroring {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("report_mirror_ports = ");
+                q.text("%#x" % self.report_mirror_ports)
+            q.breakable()
+        q.text('}')
+
+class bsn_set_pktin_suppression(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_EXPERIMENTER
+    experimenter = 0x5c16c7
+    subtype = 11
+
+    def __init__(self, xid=None, enabled=None, idle_timeout=None, hard_timeout=None, priority=None, cookie=None):
+        self.xid = xid
+        if enabled != None:
+            self.enabled = enabled
+        else:
+            self.enabled = 0
+        if idle_timeout != None:
+            self.idle_timeout = idle_timeout
+        else:
+            self.idle_timeout = 0
+        if hard_timeout != None:
+            self.hard_timeout = hard_timeout
+        else:
+            self.hard_timeout = 0
+        if priority != None:
+            self.priority = priority
+        else:
+            self.priority = 0
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        packed.append(struct.pack("!B", self.enabled))
+        packed.append('\x00' * 1)
+        packed.append(struct.pack("!H", self.idle_timeout))
+        packed.append(struct.pack("!H", self.hard_timeout))
+        packed.append(struct.pack("!H", self.priority))
+        packed.append(struct.pack("!Q", self.cookie))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = bsn_set_pktin_suppression()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_EXPERIMENTER)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 11)
+        obj.enabled = reader.read('!B')[0]
+        reader.skip(1)
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.cookie = reader.read('!Q')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.enabled != other.enabled: return False
+        if self.idle_timeout != other.idle_timeout: return False
+        if self.hard_timeout != other.hard_timeout: return False
+        if self.priority != other.priority: return False
+        if self.cookie != other.cookie: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_set_pktin_suppression {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("enabled = ");
+                q.text("%#x" % self.enabled)
+                q.text(","); q.breakable()
+                q.text("idle_timeout = ");
+                q.text("%#x" % self.idle_timeout)
+                q.text(","); q.breakable()
+                q.text("hard_timeout = ");
+                q.text("%#x" % self.hard_timeout)
+                q.text(","); q.breakable()
+                q.text("priority = ");
+                q.text("%#x" % self.priority)
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+            q.breakable()
+        q.text('}')
+
+class desc_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REPLY
+    stats_type = const.OFPST_DESC
+
+    def __init__(self, xid=None, flags=None, mfr_desc=None, hw_desc=None, sw_desc=None, serial_num=None, dp_desc=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if mfr_desc != None:
+            self.mfr_desc = mfr_desc
+        else:
+            self.mfr_desc = ""
+        if hw_desc != None:
+            self.hw_desc = hw_desc
+        else:
+            self.hw_desc = ""
+        if sw_desc != None:
+            self.sw_desc = sw_desc
+        else:
+            self.sw_desc = ""
+        if serial_num != None:
+            self.serial_num = serial_num
+        else:
+            self.serial_num = ""
+        if dp_desc != None:
+            self.dp_desc = dp_desc
+        else:
+            self.dp_desc = ""
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!256s", self.mfr_desc))
+        packed.append(struct.pack("!256s", self.hw_desc))
+        packed.append(struct.pack("!256s", self.sw_desc))
+        packed.append(struct.pack("!32s", self.serial_num))
+        packed.append(struct.pack("!256s", self.dp_desc))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = desc_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_DESC)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.mfr_desc = reader.read("!256s")[0].rstrip("\x00")
+        obj.hw_desc = reader.read("!256s")[0].rstrip("\x00")
+        obj.sw_desc = reader.read("!256s")[0].rstrip("\x00")
+        obj.serial_num = reader.read("!32s")[0].rstrip("\x00")
+        obj.dp_desc = reader.read("!256s")[0].rstrip("\x00")
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.mfr_desc != other.mfr_desc: return False
+        if self.hw_desc != other.hw_desc: return False
+        if self.sw_desc != other.sw_desc: return False
+        if self.serial_num != other.serial_num: return False
+        if self.dp_desc != other.dp_desc: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("desc_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("mfr_desc = ");
+                q.pp(self.mfr_desc)
+                q.text(","); q.breakable()
+                q.text("hw_desc = ");
+                q.pp(self.hw_desc)
+                q.text(","); q.breakable()
+                q.text("sw_desc = ");
+                q.pp(self.sw_desc)
+                q.text(","); q.breakable()
+                q.text("serial_num = ");
+                q.pp(self.serial_num)
+                q.text(","); q.breakable()
+                q.text("dp_desc = ");
+                q.pp(self.dp_desc)
+            q.breakable()
+        q.text('}')
+
+class desc_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REQUEST
+    stats_type = const.OFPST_DESC
+
+    def __init__(self, xid=None, flags=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = desc_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_DESC)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("desc_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+            q.breakable()
+        q.text('}')
+
+class echo_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_ECHO_REPLY
+
+    def __init__(self, xid=None, data=None):
+        self.xid = xid
+        if data != None:
+            self.data = data
+        else:
+            self.data = ""
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(self.data)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = echo_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_ECHO_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.data = str(reader.read_all())
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.data != other.data: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("echo_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("data = ");
+                q.pp(self.data)
+            q.breakable()
+        q.text('}')
+
+class echo_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_ECHO_REQUEST
+
+    def __init__(self, xid=None, data=None):
+        self.xid = xid
+        if data != None:
+            self.data = data
+        else:
+            self.data = ""
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(self.data)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = echo_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_ECHO_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.data = str(reader.read_all())
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.data != other.data: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("echo_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("data = ");
+                q.pp(self.data)
+            q.breakable()
+        q.text('}')
+
+class error_msg(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_ERROR
+
+    def __init__(self, xid=None, err_type=None, code=None, data=None):
+        self.xid = xid
+        if err_type != None:
+            self.err_type = err_type
+        else:
+            self.err_type = 0
+        if code != None:
+            self.code = code
+        else:
+            self.code = 0
+        if data != None:
+            self.data = data
+        else:
+            self.data = ""
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.err_type))
+        packed.append(struct.pack("!H", self.code))
+        packed.append(self.data)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = error_msg()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_ERROR)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.err_type = reader.read('!H')[0]
+        obj.code = reader.read('!H')[0]
+        obj.data = str(reader.read_all())
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.err_type != other.err_type: return False
+        if self.code != other.code: return False
+        if self.data != other.data: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("error_msg {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("err_type = ");
+                q.text("%#x" % self.err_type)
+                q.text(","); q.breakable()
+                q.text("code = ");
+                q.text("%#x" % self.code)
+                q.text(","); q.breakable()
+                q.text("data = ");
+                q.pp(self.data)
+            q.breakable()
+        q.text('}')
+
+class experimenter_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REPLY
+    stats_type = const.OFPST_EXPERIMENTER
+
+    def __init__(self, xid=None, flags=None, experimenter=None, subtype=None, data=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if experimenter != None:
+            self.experimenter = experimenter
+        else:
+            self.experimenter = 0
+        if subtype != None:
+            self.subtype = subtype
+        else:
+            self.subtype = 0
+        if data != None:
+            self.data = data
+        else:
+            self.data = ""
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        packed.append(self.data)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = experimenter_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_EXPERIMENTER)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.experimenter = reader.read('!L')[0]
+        obj.subtype = reader.read('!L')[0]
+        obj.data = str(reader.read_all())
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.experimenter != other.experimenter: return False
+        if self.subtype != other.subtype: return False
+        if self.data != other.data: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("experimenter_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("experimenter = ");
+                q.text("%#x" % self.experimenter)
+                q.text(","); q.breakable()
+                q.text("subtype = ");
+                q.text("%#x" % self.subtype)
+                q.text(","); q.breakable()
+                q.text("data = ");
+                q.pp(self.data)
+            q.breakable()
+        q.text('}')
+
+class experimenter_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REQUEST
+    stats_type = const.OFPST_EXPERIMENTER
+
+    def __init__(self, xid=None, flags=None, experimenter=None, subtype=None, data=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if experimenter != None:
+            self.experimenter = experimenter
+        else:
+            self.experimenter = 0
+        if subtype != None:
+            self.subtype = subtype
+        else:
+            self.subtype = 0
+        if data != None:
+            self.data = data
+        else:
+            self.data = ""
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        packed.append(self.data)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = experimenter_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_EXPERIMENTER)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.experimenter = reader.read('!L')[0]
+        obj.subtype = reader.read('!L')[0]
+        obj.data = str(reader.read_all())
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.experimenter != other.experimenter: return False
+        if self.subtype != other.subtype: return False
+        if self.data != other.data: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("experimenter_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("experimenter = ");
+                q.text("%#x" % self.experimenter)
+                q.text(","); q.breakable()
+                q.text("subtype = ");
+                q.text("%#x" % self.subtype)
+                q.text(","); q.breakable()
+                q.text("data = ");
+                q.pp(self.data)
+            q.breakable()
+        q.text('}')
+
+class features_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_FEATURES_REPLY
+
+    def __init__(self, xid=None, datapath_id=None, n_buffers=None, n_tables=None, capabilities=None, reserved=None, ports=None):
+        self.xid = xid
+        if datapath_id != None:
+            self.datapath_id = datapath_id
+        else:
+            self.datapath_id = 0
+        if n_buffers != None:
+            self.n_buffers = n_buffers
+        else:
+            self.n_buffers = 0
+        if n_tables != None:
+            self.n_tables = n_tables
+        else:
+            self.n_tables = 0
+        if capabilities != None:
+            self.capabilities = capabilities
+        else:
+            self.capabilities = 0
+        if reserved != None:
+            self.reserved = reserved
+        else:
+            self.reserved = 0
+        if ports != None:
+            self.ports = ports
+        else:
+            self.ports = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!Q", self.datapath_id))
+        packed.append(struct.pack("!L", self.n_buffers))
+        packed.append(struct.pack("!B", self.n_tables))
+        packed.append('\x00' * 3)
+        packed.append(struct.pack("!L", self.capabilities))
+        packed.append(struct.pack("!L", self.reserved))
+        packed.append("".join([x.pack() for x in self.ports]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = features_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FEATURES_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.datapath_id = reader.read('!Q')[0]
+        obj.n_buffers = reader.read('!L')[0]
+        obj.n_tables = reader.read('!B')[0]
+        reader.skip(3)
+        obj.capabilities = reader.read('!L')[0]
+        obj.reserved = reader.read('!L')[0]
+        obj.ports = loxi.generic_util.unpack_list(reader, common.port_desc.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.datapath_id != other.datapath_id: return False
+        if self.n_buffers != other.n_buffers: return False
+        if self.n_tables != other.n_tables: return False
+        if self.capabilities != other.capabilities: return False
+        if self.reserved != other.reserved: return False
+        if self.ports != other.ports: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("features_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("datapath_id = ");
+                q.text("%#x" % self.datapath_id)
+                q.text(","); q.breakable()
+                q.text("n_buffers = ");
+                q.text("%#x" % self.n_buffers)
+                q.text(","); q.breakable()
+                q.text("n_tables = ");
+                q.text("%#x" % self.n_tables)
+                q.text(","); q.breakable()
+                q.text("capabilities = ");
+                q.text("%#x" % self.capabilities)
+                q.text(","); q.breakable()
+                q.text("reserved = ");
+                q.text("%#x" % self.reserved)
+                q.text(","); q.breakable()
+                q.text("ports = ");
+                q.pp(self.ports)
+            q.breakable()
+        q.text('}')
+
+class features_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_FEATURES_REQUEST
+
+    def __init__(self, xid=None):
+        self.xid = xid
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = features_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FEATURES_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("features_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+            q.breakable()
+        q.text('}')
+
+class flow_add(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_FLOW_MOD
+    _command = const.OFPFC_ADD
+
+    def __init__(self, xid=None, cookie=None, cookie_mask=None, table_id=None, idle_timeout=None, hard_timeout=None, priority=None, buffer_id=None, out_port=None, out_group=None, flags=None, match=None, instructions=None):
+        self.xid = xid
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if cookie_mask != None:
+            self.cookie_mask = cookie_mask
+        else:
+            self.cookie_mask = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if idle_timeout != None:
+            self.idle_timeout = idle_timeout
+        else:
+            self.idle_timeout = 0
+        if hard_timeout != None:
+            self.hard_timeout = hard_timeout
+        else:
+            self.hard_timeout = 0
+        if priority != None:
+            self.priority = priority
+        else:
+            self.priority = 0
+        if buffer_id != None:
+            self.buffer_id = buffer_id
+        else:
+            self.buffer_id = 0
+        if out_port != None:
+            self.out_port = out_port
+        else:
+            self.out_port = 0
+        if out_group != None:
+            self.out_group = out_group
+        else:
+            self.out_group = 0
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+        if instructions != None:
+            self.instructions = instructions
+        else:
+            self.instructions = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!Q", self.cookie_mask))
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append(struct.pack("!B", self._command))
+        packed.append(struct.pack("!H", self.idle_timeout))
+        packed.append(struct.pack("!H", self.hard_timeout))
+        packed.append(struct.pack("!H", self.priority))
+        packed.append(struct.pack("!L", self.buffer_id))
+        packed.append(struct.pack("!L", self.out_port))
+        packed.append(struct.pack("!L", self.out_group))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 2)
+        packed.append(self.match.pack())
+        packed.append("".join([x.pack() for x in self.instructions]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = flow_add()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FLOW_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.cookie = reader.read('!Q')[0]
+        obj.cookie_mask = reader.read('!Q')[0]
+        obj.table_id = reader.read('!B')[0]
+        __command = reader.read('!B')[0]
+        assert(__command == const.OFPFC_ADD)
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.out_port = reader.read('!L')[0]
+        obj.out_group = reader.read('!L')[0]
+        obj.flags = reader.read('!H')[0]
+        reader.skip(2)
+        obj.match = common.match.unpack(reader)
+        obj.instructions = instruction.unpack_list(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.cookie != other.cookie: return False
+        if self.cookie_mask != other.cookie_mask: return False
+        if self.table_id != other.table_id: return False
+        if self.idle_timeout != other.idle_timeout: return False
+        if self.hard_timeout != other.hard_timeout: return False
+        if self.priority != other.priority: return False
+        if self.buffer_id != other.buffer_id: return False
+        if self.out_port != other.out_port: return False
+        if self.out_group != other.out_group: return False
+        if self.flags != other.flags: return False
+        if self.match != other.match: return False
+        if self.instructions != other.instructions: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_add {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("cookie_mask = ");
+                q.text("%#x" % self.cookie_mask)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("idle_timeout = ");
+                q.text("%#x" % self.idle_timeout)
+                q.text(","); q.breakable()
+                q.text("hard_timeout = ");
+                q.text("%#x" % self.hard_timeout)
+                q.text(","); q.breakable()
+                q.text("priority = ");
+                q.text("%#x" % self.priority)
+                q.text(","); q.breakable()
+                q.text("buffer_id = ");
+                q.text("%#x" % self.buffer_id)
+                q.text(","); q.breakable()
+                q.text("out_port = ");
+                q.text(util.pretty_port(self.out_port))
+                q.text(","); q.breakable()
+                q.text("out_group = ");
+                q.text("%#x" % self.out_group)
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+                q.text(","); q.breakable()
+                q.text("instructions = ");
+                q.pp(self.instructions)
+            q.breakable()
+        q.text('}')
+
+class flow_delete(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_FLOW_MOD
+    _command = const.OFPFC_DELETE
+
+    def __init__(self, xid=None, cookie=None, cookie_mask=None, table_id=None, idle_timeout=None, hard_timeout=None, priority=None, buffer_id=None, out_port=None, out_group=None, flags=None, match=None, instructions=None):
+        self.xid = xid
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if cookie_mask != None:
+            self.cookie_mask = cookie_mask
+        else:
+            self.cookie_mask = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if idle_timeout != None:
+            self.idle_timeout = idle_timeout
+        else:
+            self.idle_timeout = 0
+        if hard_timeout != None:
+            self.hard_timeout = hard_timeout
+        else:
+            self.hard_timeout = 0
+        if priority != None:
+            self.priority = priority
+        else:
+            self.priority = 0
+        if buffer_id != None:
+            self.buffer_id = buffer_id
+        else:
+            self.buffer_id = 0
+        if out_port != None:
+            self.out_port = out_port
+        else:
+            self.out_port = 0
+        if out_group != None:
+            self.out_group = out_group
+        else:
+            self.out_group = 0
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+        if instructions != None:
+            self.instructions = instructions
+        else:
+            self.instructions = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!Q", self.cookie_mask))
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append(struct.pack("!B", self._command))
+        packed.append(struct.pack("!H", self.idle_timeout))
+        packed.append(struct.pack("!H", self.hard_timeout))
+        packed.append(struct.pack("!H", self.priority))
+        packed.append(struct.pack("!L", self.buffer_id))
+        packed.append(struct.pack("!L", self.out_port))
+        packed.append(struct.pack("!L", self.out_group))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 2)
+        packed.append(self.match.pack())
+        packed.append("".join([x.pack() for x in self.instructions]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = flow_delete()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FLOW_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.cookie = reader.read('!Q')[0]
+        obj.cookie_mask = reader.read('!Q')[0]
+        obj.table_id = reader.read('!B')[0]
+        __command = reader.read('!B')[0]
+        assert(__command == const.OFPFC_DELETE)
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.out_port = reader.read('!L')[0]
+        obj.out_group = reader.read('!L')[0]
+        obj.flags = reader.read('!H')[0]
+        reader.skip(2)
+        obj.match = common.match.unpack(reader)
+        obj.instructions = instruction.unpack_list(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.cookie != other.cookie: return False
+        if self.cookie_mask != other.cookie_mask: return False
+        if self.table_id != other.table_id: return False
+        if self.idle_timeout != other.idle_timeout: return False
+        if self.hard_timeout != other.hard_timeout: return False
+        if self.priority != other.priority: return False
+        if self.buffer_id != other.buffer_id: return False
+        if self.out_port != other.out_port: return False
+        if self.out_group != other.out_group: return False
+        if self.flags != other.flags: return False
+        if self.match != other.match: return False
+        if self.instructions != other.instructions: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_delete {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("cookie_mask = ");
+                q.text("%#x" % self.cookie_mask)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("idle_timeout = ");
+                q.text("%#x" % self.idle_timeout)
+                q.text(","); q.breakable()
+                q.text("hard_timeout = ");
+                q.text("%#x" % self.hard_timeout)
+                q.text(","); q.breakable()
+                q.text("priority = ");
+                q.text("%#x" % self.priority)
+                q.text(","); q.breakable()
+                q.text("buffer_id = ");
+                q.text("%#x" % self.buffer_id)
+                q.text(","); q.breakable()
+                q.text("out_port = ");
+                q.text(util.pretty_port(self.out_port))
+                q.text(","); q.breakable()
+                q.text("out_group = ");
+                q.text("%#x" % self.out_group)
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+                q.text(","); q.breakable()
+                q.text("instructions = ");
+                q.pp(self.instructions)
+            q.breakable()
+        q.text('}')
+
+class flow_delete_strict(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_FLOW_MOD
+    _command = const.OFPFC_DELETE_STRICT
+
+    def __init__(self, xid=None, cookie=None, cookie_mask=None, table_id=None, idle_timeout=None, hard_timeout=None, priority=None, buffer_id=None, out_port=None, out_group=None, flags=None, match=None, instructions=None):
+        self.xid = xid
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if cookie_mask != None:
+            self.cookie_mask = cookie_mask
+        else:
+            self.cookie_mask = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if idle_timeout != None:
+            self.idle_timeout = idle_timeout
+        else:
+            self.idle_timeout = 0
+        if hard_timeout != None:
+            self.hard_timeout = hard_timeout
+        else:
+            self.hard_timeout = 0
+        if priority != None:
+            self.priority = priority
+        else:
+            self.priority = 0
+        if buffer_id != None:
+            self.buffer_id = buffer_id
+        else:
+            self.buffer_id = 0
+        if out_port != None:
+            self.out_port = out_port
+        else:
+            self.out_port = 0
+        if out_group != None:
+            self.out_group = out_group
+        else:
+            self.out_group = 0
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+        if instructions != None:
+            self.instructions = instructions
+        else:
+            self.instructions = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!Q", self.cookie_mask))
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append(struct.pack("!B", self._command))
+        packed.append(struct.pack("!H", self.idle_timeout))
+        packed.append(struct.pack("!H", self.hard_timeout))
+        packed.append(struct.pack("!H", self.priority))
+        packed.append(struct.pack("!L", self.buffer_id))
+        packed.append(struct.pack("!L", self.out_port))
+        packed.append(struct.pack("!L", self.out_group))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 2)
+        packed.append(self.match.pack())
+        packed.append("".join([x.pack() for x in self.instructions]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = flow_delete_strict()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FLOW_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.cookie = reader.read('!Q')[0]
+        obj.cookie_mask = reader.read('!Q')[0]
+        obj.table_id = reader.read('!B')[0]
+        __command = reader.read('!B')[0]
+        assert(__command == const.OFPFC_DELETE_STRICT)
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.out_port = reader.read('!L')[0]
+        obj.out_group = reader.read('!L')[0]
+        obj.flags = reader.read('!H')[0]
+        reader.skip(2)
+        obj.match = common.match.unpack(reader)
+        obj.instructions = instruction.unpack_list(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.cookie != other.cookie: return False
+        if self.cookie_mask != other.cookie_mask: return False
+        if self.table_id != other.table_id: return False
+        if self.idle_timeout != other.idle_timeout: return False
+        if self.hard_timeout != other.hard_timeout: return False
+        if self.priority != other.priority: return False
+        if self.buffer_id != other.buffer_id: return False
+        if self.out_port != other.out_port: return False
+        if self.out_group != other.out_group: return False
+        if self.flags != other.flags: return False
+        if self.match != other.match: return False
+        if self.instructions != other.instructions: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_delete_strict {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("cookie_mask = ");
+                q.text("%#x" % self.cookie_mask)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("idle_timeout = ");
+                q.text("%#x" % self.idle_timeout)
+                q.text(","); q.breakable()
+                q.text("hard_timeout = ");
+                q.text("%#x" % self.hard_timeout)
+                q.text(","); q.breakable()
+                q.text("priority = ");
+                q.text("%#x" % self.priority)
+                q.text(","); q.breakable()
+                q.text("buffer_id = ");
+                q.text("%#x" % self.buffer_id)
+                q.text(","); q.breakable()
+                q.text("out_port = ");
+                q.text(util.pretty_port(self.out_port))
+                q.text(","); q.breakable()
+                q.text("out_group = ");
+                q.text("%#x" % self.out_group)
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+                q.text(","); q.breakable()
+                q.text("instructions = ");
+                q.pp(self.instructions)
+            q.breakable()
+        q.text('}')
+
+class flow_modify(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_FLOW_MOD
+    _command = const.OFPFC_MODIFY
+
+    def __init__(self, xid=None, cookie=None, cookie_mask=None, table_id=None, idle_timeout=None, hard_timeout=None, priority=None, buffer_id=None, out_port=None, out_group=None, flags=None, match=None, instructions=None):
+        self.xid = xid
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if cookie_mask != None:
+            self.cookie_mask = cookie_mask
+        else:
+            self.cookie_mask = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if idle_timeout != None:
+            self.idle_timeout = idle_timeout
+        else:
+            self.idle_timeout = 0
+        if hard_timeout != None:
+            self.hard_timeout = hard_timeout
+        else:
+            self.hard_timeout = 0
+        if priority != None:
+            self.priority = priority
+        else:
+            self.priority = 0
+        if buffer_id != None:
+            self.buffer_id = buffer_id
+        else:
+            self.buffer_id = 0
+        if out_port != None:
+            self.out_port = out_port
+        else:
+            self.out_port = 0
+        if out_group != None:
+            self.out_group = out_group
+        else:
+            self.out_group = 0
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+        if instructions != None:
+            self.instructions = instructions
+        else:
+            self.instructions = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!Q", self.cookie_mask))
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append(struct.pack("!B", self._command))
+        packed.append(struct.pack("!H", self.idle_timeout))
+        packed.append(struct.pack("!H", self.hard_timeout))
+        packed.append(struct.pack("!H", self.priority))
+        packed.append(struct.pack("!L", self.buffer_id))
+        packed.append(struct.pack("!L", self.out_port))
+        packed.append(struct.pack("!L", self.out_group))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 2)
+        packed.append(self.match.pack())
+        packed.append("".join([x.pack() for x in self.instructions]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = flow_modify()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FLOW_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.cookie = reader.read('!Q')[0]
+        obj.cookie_mask = reader.read('!Q')[0]
+        obj.table_id = reader.read('!B')[0]
+        __command = reader.read('!B')[0]
+        assert(__command == const.OFPFC_MODIFY)
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.out_port = reader.read('!L')[0]
+        obj.out_group = reader.read('!L')[0]
+        obj.flags = reader.read('!H')[0]
+        reader.skip(2)
+        obj.match = common.match.unpack(reader)
+        obj.instructions = instruction.unpack_list(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.cookie != other.cookie: return False
+        if self.cookie_mask != other.cookie_mask: return False
+        if self.table_id != other.table_id: return False
+        if self.idle_timeout != other.idle_timeout: return False
+        if self.hard_timeout != other.hard_timeout: return False
+        if self.priority != other.priority: return False
+        if self.buffer_id != other.buffer_id: return False
+        if self.out_port != other.out_port: return False
+        if self.out_group != other.out_group: return False
+        if self.flags != other.flags: return False
+        if self.match != other.match: return False
+        if self.instructions != other.instructions: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_modify {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("cookie_mask = ");
+                q.text("%#x" % self.cookie_mask)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("idle_timeout = ");
+                q.text("%#x" % self.idle_timeout)
+                q.text(","); q.breakable()
+                q.text("hard_timeout = ");
+                q.text("%#x" % self.hard_timeout)
+                q.text(","); q.breakable()
+                q.text("priority = ");
+                q.text("%#x" % self.priority)
+                q.text(","); q.breakable()
+                q.text("buffer_id = ");
+                q.text("%#x" % self.buffer_id)
+                q.text(","); q.breakable()
+                q.text("out_port = ");
+                q.text(util.pretty_port(self.out_port))
+                q.text(","); q.breakable()
+                q.text("out_group = ");
+                q.text("%#x" % self.out_group)
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+                q.text(","); q.breakable()
+                q.text("instructions = ");
+                q.pp(self.instructions)
+            q.breakable()
+        q.text('}')
+
+class flow_modify_strict(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_FLOW_MOD
+    _command = const.OFPFC_MODIFY_STRICT
+
+    def __init__(self, xid=None, cookie=None, cookie_mask=None, table_id=None, idle_timeout=None, hard_timeout=None, priority=None, buffer_id=None, out_port=None, out_group=None, flags=None, match=None, instructions=None):
+        self.xid = xid
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if cookie_mask != None:
+            self.cookie_mask = cookie_mask
+        else:
+            self.cookie_mask = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if idle_timeout != None:
+            self.idle_timeout = idle_timeout
+        else:
+            self.idle_timeout = 0
+        if hard_timeout != None:
+            self.hard_timeout = hard_timeout
+        else:
+            self.hard_timeout = 0
+        if priority != None:
+            self.priority = priority
+        else:
+            self.priority = 0
+        if buffer_id != None:
+            self.buffer_id = buffer_id
+        else:
+            self.buffer_id = 0
+        if out_port != None:
+            self.out_port = out_port
+        else:
+            self.out_port = 0
+        if out_group != None:
+            self.out_group = out_group
+        else:
+            self.out_group = 0
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+        if instructions != None:
+            self.instructions = instructions
+        else:
+            self.instructions = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!Q", self.cookie_mask))
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append(struct.pack("!B", self._command))
+        packed.append(struct.pack("!H", self.idle_timeout))
+        packed.append(struct.pack("!H", self.hard_timeout))
+        packed.append(struct.pack("!H", self.priority))
+        packed.append(struct.pack("!L", self.buffer_id))
+        packed.append(struct.pack("!L", self.out_port))
+        packed.append(struct.pack("!L", self.out_group))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 2)
+        packed.append(self.match.pack())
+        packed.append("".join([x.pack() for x in self.instructions]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = flow_modify_strict()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FLOW_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.cookie = reader.read('!Q')[0]
+        obj.cookie_mask = reader.read('!Q')[0]
+        obj.table_id = reader.read('!B')[0]
+        __command = reader.read('!B')[0]
+        assert(__command == const.OFPFC_MODIFY_STRICT)
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.out_port = reader.read('!L')[0]
+        obj.out_group = reader.read('!L')[0]
+        obj.flags = reader.read('!H')[0]
+        reader.skip(2)
+        obj.match = common.match.unpack(reader)
+        obj.instructions = instruction.unpack_list(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.cookie != other.cookie: return False
+        if self.cookie_mask != other.cookie_mask: return False
+        if self.table_id != other.table_id: return False
+        if self.idle_timeout != other.idle_timeout: return False
+        if self.hard_timeout != other.hard_timeout: return False
+        if self.priority != other.priority: return False
+        if self.buffer_id != other.buffer_id: return False
+        if self.out_port != other.out_port: return False
+        if self.out_group != other.out_group: return False
+        if self.flags != other.flags: return False
+        if self.match != other.match: return False
+        if self.instructions != other.instructions: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_modify_strict {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("cookie_mask = ");
+                q.text("%#x" % self.cookie_mask)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("idle_timeout = ");
+                q.text("%#x" % self.idle_timeout)
+                q.text(","); q.breakable()
+                q.text("hard_timeout = ");
+                q.text("%#x" % self.hard_timeout)
+                q.text(","); q.breakable()
+                q.text("priority = ");
+                q.text("%#x" % self.priority)
+                q.text(","); q.breakable()
+                q.text("buffer_id = ");
+                q.text("%#x" % self.buffer_id)
+                q.text(","); q.breakable()
+                q.text("out_port = ");
+                q.text(util.pretty_port(self.out_port))
+                q.text(","); q.breakable()
+                q.text("out_group = ");
+                q.text("%#x" % self.out_group)
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+                q.text(","); q.breakable()
+                q.text("instructions = ");
+                q.pp(self.instructions)
+            q.breakable()
+        q.text('}')
+
+class flow_removed(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_FLOW_REMOVED
+
+    def __init__(self, xid=None, cookie=None, priority=None, reason=None, table_id=None, duration_sec=None, duration_nsec=None, idle_timeout=None, hard_timeout=None, packet_count=None, byte_count=None, match=None):
+        self.xid = xid
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if priority != None:
+            self.priority = priority
+        else:
+            self.priority = 0
+        if reason != None:
+            self.reason = reason
+        else:
+            self.reason = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if duration_sec != None:
+            self.duration_sec = duration_sec
+        else:
+            self.duration_sec = 0
+        if duration_nsec != None:
+            self.duration_nsec = duration_nsec
+        else:
+            self.duration_nsec = 0
+        if idle_timeout != None:
+            self.idle_timeout = idle_timeout
+        else:
+            self.idle_timeout = 0
+        if hard_timeout != None:
+            self.hard_timeout = hard_timeout
+        else:
+            self.hard_timeout = 0
+        if packet_count != None:
+            self.packet_count = packet_count
+        else:
+            self.packet_count = 0
+        if byte_count != None:
+            self.byte_count = byte_count
+        else:
+            self.byte_count = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!H", self.priority))
+        packed.append(struct.pack("!B", self.reason))
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append(struct.pack("!L", self.duration_sec))
+        packed.append(struct.pack("!L", self.duration_nsec))
+        packed.append(struct.pack("!H", self.idle_timeout))
+        packed.append(struct.pack("!H", self.hard_timeout))
+        packed.append(struct.pack("!Q", self.packet_count))
+        packed.append(struct.pack("!Q", self.byte_count))
+        packed.append(self.match.pack())
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = flow_removed()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FLOW_REMOVED)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.cookie = reader.read('!Q')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.reason = reader.read('!B')[0]
+        obj.table_id = reader.read('!B')[0]
+        obj.duration_sec = reader.read('!L')[0]
+        obj.duration_nsec = reader.read('!L')[0]
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        obj.packet_count = reader.read('!Q')[0]
+        obj.byte_count = reader.read('!Q')[0]
+        obj.match = common.match.unpack(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.cookie != other.cookie: return False
+        if self.priority != other.priority: return False
+        if self.reason != other.reason: return False
+        if self.table_id != other.table_id: return False
+        if self.duration_sec != other.duration_sec: return False
+        if self.duration_nsec != other.duration_nsec: return False
+        if self.idle_timeout != other.idle_timeout: return False
+        if self.hard_timeout != other.hard_timeout: return False
+        if self.packet_count != other.packet_count: return False
+        if self.byte_count != other.byte_count: return False
+        if self.match != other.match: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_removed {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("priority = ");
+                q.text("%#x" % self.priority)
+                q.text(","); q.breakable()
+                q.text("reason = ");
+                q.text("%#x" % self.reason)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("duration_sec = ");
+                q.text("%#x" % self.duration_sec)
+                q.text(","); q.breakable()
+                q.text("duration_nsec = ");
+                q.text("%#x" % self.duration_nsec)
+                q.text(","); q.breakable()
+                q.text("idle_timeout = ");
+                q.text("%#x" % self.idle_timeout)
+                q.text(","); q.breakable()
+                q.text("hard_timeout = ");
+                q.text("%#x" % self.hard_timeout)
+                q.text(","); q.breakable()
+                q.text("packet_count = ");
+                q.text("%#x" % self.packet_count)
+                q.text(","); q.breakable()
+                q.text("byte_count = ");
+                q.text("%#x" % self.byte_count)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+            q.breakable()
+        q.text('}')
+
+class flow_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REPLY
+    stats_type = const.OFPST_FLOW
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.entries]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = flow_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_FLOW)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.entries = common.unpack_list_flow_stats_entry(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.entries != other.entries: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("entries = ");
+                q.pp(self.entries)
+            q.breakable()
+        q.text('}')
+
+class flow_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REQUEST
+    stats_type = const.OFPST_FLOW
+
+    def __init__(self, xid=None, flags=None, table_id=None, out_port=None, out_group=None, cookie=None, cookie_mask=None, match=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if out_port != None:
+            self.out_port = out_port
+        else:
+            self.out_port = 0
+        if out_group != None:
+            self.out_group = out_group
+        else:
+            self.out_group = 0
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if cookie_mask != None:
+            self.cookie_mask = cookie_mask
+        else:
+            self.cookie_mask = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append('\x00' * 3)
+        packed.append(struct.pack("!L", self.out_port))
+        packed.append(struct.pack("!L", self.out_group))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!Q", self.cookie_mask))
+        packed.append(self.match.pack())
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = flow_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_FLOW)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.table_id = reader.read('!B')[0]
+        reader.skip(3)
+        obj.out_port = reader.read('!L')[0]
+        obj.out_group = reader.read('!L')[0]
+        reader.skip(4)
+        obj.cookie = reader.read('!Q')[0]
+        obj.cookie_mask = reader.read('!Q')[0]
+        obj.match = common.match.unpack(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.table_id != other.table_id: return False
+        if self.out_port != other.out_port: return False
+        if self.out_group != other.out_group: return False
+        if self.cookie != other.cookie: return False
+        if self.cookie_mask != other.cookie_mask: return False
+        if self.match != other.match: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("out_port = ");
+                q.text(util.pretty_port(self.out_port))
+                q.text(","); q.breakable()
+                q.text("out_group = ");
+                q.text("%#x" % self.out_group)
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("cookie_mask = ");
+                q.text("%#x" % self.cookie_mask)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+            q.breakable()
+        q.text('}')
+
+class get_config_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_GET_CONFIG_REPLY
+
+    def __init__(self, xid=None, flags=None, miss_send_len=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if miss_send_len != None:
+            self.miss_send_len = miss_send_len
+        else:
+            self.miss_send_len = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append(struct.pack("!H", self.miss_send_len))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = get_config_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_GET_CONFIG_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.flags = reader.read('!H')[0]
+        obj.miss_send_len = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.miss_send_len != other.miss_send_len: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("get_config_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("miss_send_len = ");
+                q.text("%#x" % self.miss_send_len)
+            q.breakable()
+        q.text('}')
+
+class get_config_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_GET_CONFIG_REQUEST
+
+    def __init__(self, xid=None):
+        self.xid = xid
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = get_config_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_GET_CONFIG_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("get_config_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+            q.breakable()
+        q.text('}')
+
+class group_desc_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REPLY
+    stats_type = const.OFPST_GROUP_DESC
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.entries]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = group_desc_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_GROUP_DESC)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.entries = common.unpack_list_group_desc_stats_entry(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.entries != other.entries: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group_desc_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("entries = ");
+                q.pp(self.entries)
+            q.breakable()
+        q.text('}')
+
+class group_desc_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REQUEST
+    stats_type = const.OFPST_GROUP_DESC
+
+    def __init__(self, xid=None, flags=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = group_desc_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_GROUP_DESC)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group_desc_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+            q.breakable()
+        q.text('}')
+
+class group_features_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REPLY
+    stats_type = const.OFPST_GROUP_FEATURES
+
+    def __init__(self, xid=None, flags=None, types=None, capabilities=None, max_groups_all=None, max_groups_select=None, max_groups_indirect=None, max_groups_ff=None, actions_all=None, actions_select=None, actions_indirect=None, actions_ff=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if types != None:
+            self.types = types
+        else:
+            self.types = 0
+        if capabilities != None:
+            self.capabilities = capabilities
+        else:
+            self.capabilities = 0
+        if max_groups_all != None:
+            self.max_groups_all = max_groups_all
+        else:
+            self.max_groups_all = 0
+        if max_groups_select != None:
+            self.max_groups_select = max_groups_select
+        else:
+            self.max_groups_select = 0
+        if max_groups_indirect != None:
+            self.max_groups_indirect = max_groups_indirect
+        else:
+            self.max_groups_indirect = 0
+        if max_groups_ff != None:
+            self.max_groups_ff = max_groups_ff
+        else:
+            self.max_groups_ff = 0
+        if actions_all != None:
+            self.actions_all = actions_all
+        else:
+            self.actions_all = 0
+        if actions_select != None:
+            self.actions_select = actions_select
+        else:
+            self.actions_select = 0
+        if actions_indirect != None:
+            self.actions_indirect = actions_indirect
+        else:
+            self.actions_indirect = 0
+        if actions_ff != None:
+            self.actions_ff = actions_ff
+        else:
+            self.actions_ff = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!L", self.types))
+        packed.append(struct.pack("!L", self.capabilities))
+        packed.append(struct.pack("!L", self.max_groups_all))
+        packed.append(struct.pack("!L", self.max_groups_select))
+        packed.append(struct.pack("!L", self.max_groups_indirect))
+        packed.append(struct.pack("!L", self.max_groups_ff))
+        packed.append(struct.pack("!L", self.actions_all))
+        packed.append(struct.pack("!L", self.actions_select))
+        packed.append(struct.pack("!L", self.actions_indirect))
+        packed.append(struct.pack("!L", self.actions_ff))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = group_features_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_GROUP_FEATURES)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.types = reader.read('!L')[0]
+        obj.capabilities = reader.read('!L')[0]
+        obj.max_groups_all = reader.read('!L')[0]
+        obj.max_groups_select = reader.read('!L')[0]
+        obj.max_groups_indirect = reader.read('!L')[0]
+        obj.max_groups_ff = reader.read('!L')[0]
+        obj.actions_all = reader.read('!L')[0]
+        obj.actions_select = reader.read('!L')[0]
+        obj.actions_indirect = reader.read('!L')[0]
+        obj.actions_ff = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.types != other.types: return False
+        if self.capabilities != other.capabilities: return False
+        if self.max_groups_all != other.max_groups_all: return False
+        if self.max_groups_select != other.max_groups_select: return False
+        if self.max_groups_indirect != other.max_groups_indirect: return False
+        if self.max_groups_ff != other.max_groups_ff: return False
+        if self.actions_all != other.actions_all: return False
+        if self.actions_select != other.actions_select: return False
+        if self.actions_indirect != other.actions_indirect: return False
+        if self.actions_ff != other.actions_ff: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group_features_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("types = ");
+                q.text("%#x" % self.types)
+                q.text(","); q.breakable()
+                q.text("capabilities = ");
+                q.text("%#x" % self.capabilities)
+                q.text(","); q.breakable()
+                q.text("max_groups_all = ");
+                q.text("%#x" % self.max_groups_all)
+                q.text(","); q.breakable()
+                q.text("max_groups_select = ");
+                q.text("%#x" % self.max_groups_select)
+                q.text(","); q.breakable()
+                q.text("max_groups_indirect = ");
+                q.text("%#x" % self.max_groups_indirect)
+                q.text(","); q.breakable()
+                q.text("max_groups_ff = ");
+                q.text("%#x" % self.max_groups_ff)
+                q.text(","); q.breakable()
+                q.text("actions_all = ");
+                q.text("%#x" % self.actions_all)
+                q.text(","); q.breakable()
+                q.text("actions_select = ");
+                q.text("%#x" % self.actions_select)
+                q.text(","); q.breakable()
+                q.text("actions_indirect = ");
+                q.text("%#x" % self.actions_indirect)
+                q.text(","); q.breakable()
+                q.text("actions_ff = ");
+                q.text("%#x" % self.actions_ff)
+            q.breakable()
+        q.text('}')
+
+class group_features_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REQUEST
+    stats_type = const.OFPST_GROUP_FEATURES
+
+    def __init__(self, xid=None, flags=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = group_features_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_GROUP_FEATURES)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group_features_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+            q.breakable()
+        q.text('}')
+
+class group_mod(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_GROUP_MOD
+
+    def __init__(self, xid=None, command=None, group_type=None, group_id=None, buckets=None):
+        self.xid = xid
+        if command != None:
+            self.command = command
+        else:
+            self.command = 0
+        if group_type != None:
+            self.group_type = group_type
+        else:
+            self.group_type = 0
+        if group_id != None:
+            self.group_id = group_id
+        else:
+            self.group_id = 0
+        if buckets != None:
+            self.buckets = buckets
+        else:
+            self.buckets = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.command))
+        packed.append(struct.pack("!B", self.group_type))
+        packed.append('\x00' * 1)
+        packed.append(struct.pack("!L", self.group_id))
+        packed.append("".join([x.pack() for x in self.buckets]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = group_mod()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_GROUP_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.command = reader.read('!H')[0]
+        obj.group_type = reader.read('!B')[0]
+        reader.skip(1)
+        obj.group_id = reader.read('!L')[0]
+        obj.buckets = common.unpack_list_bucket(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.command != other.command: return False
+        if self.group_type != other.group_type: return False
+        if self.group_id != other.group_id: return False
+        if self.buckets != other.buckets: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group_mod {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("command = ");
+                q.text("%#x" % self.command)
+                q.text(","); q.breakable()
+                q.text("group_type = ");
+                q.text("%#x" % self.group_type)
+                q.text(","); q.breakable()
+                q.text("group_id = ");
+                q.text("%#x" % self.group_id)
+                q.text(","); q.breakable()
+                q.text("buckets = ");
+                q.pp(self.buckets)
+            q.breakable()
+        q.text('}')
+
+class group_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REPLY
+    stats_type = const.OFPST_GROUP
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.entries]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = group_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_GROUP)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.entries = common.unpack_list_group_stats_entry(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.entries != other.entries: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("entries = ");
+                q.pp(self.entries)
+            q.breakable()
+        q.text('}')
+
+class group_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REQUEST
+    stats_type = const.OFPST_GROUP
+
+    def __init__(self, xid=None, flags=None, group_id=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if group_id != None:
+            self.group_id = group_id
+        else:
+            self.group_id = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!L", self.group_id))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = group_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_GROUP)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.group_id = reader.read('!L')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.group_id != other.group_id: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("group_id = ");
+                q.text("%#x" % self.group_id)
+            q.breakable()
+        q.text('}')
+
+class hello(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_HELLO
+
+    def __init__(self, xid=None):
+        self.xid = xid
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = hello()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_HELLO)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("hello {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+            q.breakable()
+        q.text('}')
+
+class packet_in(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_PACKET_IN
+
+    def __init__(self, xid=None, buffer_id=None, total_len=None, reason=None, table_id=None, match=None, data=None):
+        self.xid = xid
+        if buffer_id != None:
+            self.buffer_id = buffer_id
+        else:
+            self.buffer_id = 0
+        if total_len != None:
+            self.total_len = total_len
+        else:
+            self.total_len = 0
+        if reason != None:
+            self.reason = reason
+        else:
+            self.reason = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+        if data != None:
+            self.data = data
+        else:
+            self.data = ""
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.buffer_id))
+        packed.append(struct.pack("!H", self.total_len))
+        packed.append(struct.pack("!B", self.reason))
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append(self.match.pack())
+        packed.append('\x00' * 2)
+        packed.append(self.data)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = packet_in()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_PACKET_IN)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.total_len = reader.read('!H')[0]
+        obj.reason = reader.read('!B')[0]
+        obj.table_id = reader.read('!B')[0]
+        obj.match = common.match.unpack(reader)
+        reader.skip(2)
+        obj.data = str(reader.read_all())
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.buffer_id != other.buffer_id: return False
+        if self.total_len != other.total_len: return False
+        if self.reason != other.reason: return False
+        if self.table_id != other.table_id: return False
+        if self.match != other.match: return False
+        if self.data != other.data: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("packet_in {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("buffer_id = ");
+                q.text("%#x" % self.buffer_id)
+                q.text(","); q.breakable()
+                q.text("total_len = ");
+                q.text("%#x" % self.total_len)
+                q.text(","); q.breakable()
+                q.text("reason = ");
+                q.text("%#x" % self.reason)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+                q.text(","); q.breakable()
+                q.text("data = ");
+                q.pp(self.data)
+            q.breakable()
+        q.text('}')
+
+class packet_out(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_PACKET_OUT
+
+    def __init__(self, xid=None, buffer_id=None, in_port=None, actions=None, data=None):
+        self.xid = xid
+        if buffer_id != None:
+            self.buffer_id = buffer_id
+        else:
+            self.buffer_id = 0
+        if in_port != None:
+            self.in_port = in_port
+        else:
+            self.in_port = 0
+        if actions != None:
+            self.actions = actions
+        else:
+            self.actions = []
+        if data != None:
+            self.data = data
+        else:
+            self.data = ""
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.buffer_id))
+        packed.append(struct.pack("!L", self.in_port))
+        packed.append(struct.pack("!H", 0)) # placeholder for actions_len at index 6
+        packed.append('\x00' * 6)
+        packed.append("".join([x.pack() for x in self.actions]))
+        packed[6] = struct.pack("!H", len(packed[-1]))
+        packed.append(self.data)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = packet_out()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_PACKET_OUT)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.in_port = reader.read('!L')[0]
+        _actions_len = reader.read('!H')[0]
+        reader.skip(6)
+        obj.actions = action.unpack_list(reader.slice(_actions_len))
+        obj.data = str(reader.read_all())
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.buffer_id != other.buffer_id: return False
+        if self.in_port != other.in_port: return False
+        if self.actions != other.actions: return False
+        if self.data != other.data: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("packet_out {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("buffer_id = ");
+                q.text("%#x" % self.buffer_id)
+                q.text(","); q.breakable()
+                q.text("in_port = ");
+                q.text(util.pretty_port(self.in_port))
+                q.text(","); q.breakable()
+                q.text("actions = ");
+                q.pp(self.actions)
+                q.text(","); q.breakable()
+                q.text("data = ");
+                q.pp(self.data)
+            q.breakable()
+        q.text('}')
+
+class port_mod(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_PORT_MOD
+
+    def __init__(self, xid=None, port_no=None, hw_addr=None, config=None, mask=None, advertise=None):
+        self.xid = xid
+        if port_no != None:
+            self.port_no = port_no
+        else:
+            self.port_no = 0
+        if hw_addr != None:
+            self.hw_addr = hw_addr
+        else:
+            self.hw_addr = [0,0,0,0,0,0]
+        if config != None:
+            self.config = config
+        else:
+            self.config = 0
+        if mask != None:
+            self.mask = mask
+        else:
+            self.mask = 0
+        if advertise != None:
+            self.advertise = advertise
+        else:
+            self.advertise = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.port_no))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!6B", *self.hw_addr))
+        packed.append('\x00' * 2)
+        packed.append(struct.pack("!L", self.config))
+        packed.append(struct.pack("!L", self.mask))
+        packed.append(struct.pack("!L", self.advertise))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = port_mod()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_PORT_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.port_no = reader.read('!L')[0]
+        reader.skip(4)
+        obj.hw_addr = list(reader.read('!6B'))
+        reader.skip(2)
+        obj.config = reader.read('!L')[0]
+        obj.mask = reader.read('!L')[0]
+        obj.advertise = reader.read('!L')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.port_no != other.port_no: return False
+        if self.hw_addr != other.hw_addr: return False
+        if self.config != other.config: return False
+        if self.mask != other.mask: return False
+        if self.advertise != other.advertise: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("port_mod {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("port_no = ");
+                q.text(util.pretty_port(self.port_no))
+                q.text(","); q.breakable()
+                q.text("hw_addr = ");
+                q.text(util.pretty_mac(self.hw_addr))
+                q.text(","); q.breakable()
+                q.text("config = ");
+                q.text("%#x" % self.config)
+                q.text(","); q.breakable()
+                q.text("mask = ");
+                q.text("%#x" % self.mask)
+                q.text(","); q.breakable()
+                q.text("advertise = ");
+                q.text("%#x" % self.advertise)
+            q.breakable()
+        q.text('}')
+
+class port_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REPLY
+    stats_type = const.OFPST_PORT
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.entries]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = port_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_PORT)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.entries = loxi.generic_util.unpack_list(reader, common.port_stats_entry.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.entries != other.entries: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("port_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("entries = ");
+                q.pp(self.entries)
+            q.breakable()
+        q.text('}')
+
+class port_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REQUEST
+    stats_type = const.OFPST_PORT
+
+    def __init__(self, xid=None, flags=None, port_no=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if port_no != None:
+            self.port_no = port_no
+        else:
+            self.port_no = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!L", self.port_no))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = port_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_PORT)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.port_no = reader.read('!L')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.port_no != other.port_no: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("port_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("port_no = ");
+                q.text(util.pretty_port(self.port_no))
+            q.breakable()
+        q.text('}')
+
+class port_status(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_PORT_STATUS
+
+    def __init__(self, xid=None, reason=None, desc=None):
+        self.xid = xid
+        if reason != None:
+            self.reason = reason
+        else:
+            self.reason = 0
+        if desc != None:
+            self.desc = desc
+        else:
+            self.desc = common.port_desc()
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!B", self.reason))
+        packed.append('\x00' * 7)
+        packed.append(self.desc.pack())
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = port_status()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_PORT_STATUS)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.reason = reader.read('!B')[0]
+        reader.skip(7)
+        obj.desc = common.port_desc.unpack(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.reason != other.reason: return False
+        if self.desc != other.desc: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("port_status {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("reason = ");
+                q.text("%#x" % self.reason)
+                q.text(","); q.breakable()
+                q.text("desc = ");
+                q.pp(self.desc)
+            q.breakable()
+        q.text('}')
+
+class queue_get_config_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_QUEUE_GET_CONFIG_REPLY
+
+    def __init__(self, xid=None, port=None, queues=None):
+        self.xid = xid
+        if port != None:
+            self.port = port
+        else:
+            self.port = 0
+        if queues != None:
+            self.queues = queues
+        else:
+            self.queues = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.port))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.queues]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = queue_get_config_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_QUEUE_GET_CONFIG_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.port = reader.read('!L')[0]
+        reader.skip(4)
+        obj.queues = common.unpack_list_packet_queue(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.port != other.port: return False
+        if self.queues != other.queues: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("queue_get_config_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("port = ");
+                q.text(util.pretty_port(self.port))
+                q.text(","); q.breakable()
+                q.text("queues = ");
+                q.pp(self.queues)
+            q.breakable()
+        q.text('}')
+
+class queue_get_config_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_QUEUE_GET_CONFIG_REQUEST
+
+    def __init__(self, xid=None, port=None):
+        self.xid = xid
+        if port != None:
+            self.port = port
+        else:
+            self.port = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.port))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = queue_get_config_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_QUEUE_GET_CONFIG_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.port = reader.read('!L')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.port != other.port: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("queue_get_config_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("port = ");
+                q.text(util.pretty_port(self.port))
+            q.breakable()
+        q.text('}')
+
+class queue_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REPLY
+    stats_type = const.OFPST_QUEUE
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.entries]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = queue_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_QUEUE)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.entries = loxi.generic_util.unpack_list(reader, common.queue_stats_entry.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.entries != other.entries: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("queue_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("entries = ");
+                q.pp(self.entries)
+            q.breakable()
+        q.text('}')
+
+class queue_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REQUEST
+    stats_type = const.OFPST_QUEUE
+
+    def __init__(self, xid=None, flags=None, port_no=None, queue_id=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if port_no != None:
+            self.port_no = port_no
+        else:
+            self.port_no = 0
+        if queue_id != None:
+            self.queue_id = queue_id
+        else:
+            self.queue_id = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!L", self.port_no))
+        packed.append(struct.pack("!L", self.queue_id))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = queue_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_QUEUE)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.port_no = reader.read('!L')[0]
+        obj.queue_id = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.port_no != other.port_no: return False
+        if self.queue_id != other.queue_id: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("queue_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("port_no = ");
+                q.text(util.pretty_port(self.port_no))
+                q.text(","); q.breakable()
+                q.text("queue_id = ");
+                q.text("%#x" % self.queue_id)
+            q.breakable()
+        q.text('}')
+
+class role_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_ROLE_REPLY
+
+    def __init__(self, xid=None, data=None):
+        self.xid = xid
+        if data != None:
+            self.data = data
+        else:
+            self.data = ""
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(self.data)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = role_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_ROLE_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.data = str(reader.read_all())
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.data != other.data: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("role_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("data = ");
+                q.pp(self.data)
+            q.breakable()
+        q.text('}')
+
+class role_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_ROLE_REQUEST
+
+    def __init__(self, xid=None, role=None, generation_id=None):
+        self.xid = xid
+        if role != None:
+            self.role = role
+        else:
+            self.role = 0
+        if generation_id != None:
+            self.generation_id = generation_id
+        else:
+            self.generation_id = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.role))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!Q", self.generation_id))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = role_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_ROLE_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.role = reader.read('!L')[0]
+        reader.skip(4)
+        obj.generation_id = reader.read('!Q')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.role != other.role: return False
+        if self.generation_id != other.generation_id: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("role_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("role = ");
+                q.text("%#x" % self.role)
+                q.text(","); q.breakable()
+                q.text("generation_id = ");
+                q.text("%#x" % self.generation_id)
+            q.breakable()
+        q.text('}')
+
+class set_config(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_SET_CONFIG
+
+    def __init__(self, xid=None, flags=None, miss_send_len=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if miss_send_len != None:
+            self.miss_send_len = miss_send_len
+        else:
+            self.miss_send_len = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append(struct.pack("!H", self.miss_send_len))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = set_config()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_SET_CONFIG)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.flags = reader.read('!H')[0]
+        obj.miss_send_len = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.miss_send_len != other.miss_send_len: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("set_config {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("miss_send_len = ");
+                q.text("%#x" % self.miss_send_len)
+            q.breakable()
+        q.text('}')
+
+class table_mod(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_TABLE_MOD
+
+    def __init__(self, xid=None, table_id=None, config=None):
+        self.xid = xid
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if config != None:
+            self.config = config
+        else:
+            self.config = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append('\x00' * 3)
+        packed.append(struct.pack("!L", self.config))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = table_mod()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_TABLE_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.table_id = reader.read('!B')[0]
+        reader.skip(3)
+        obj.config = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.table_id != other.table_id: return False
+        if self.config != other.config: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_mod {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("config = ");
+                q.text("%#x" % self.config)
+            q.breakable()
+        q.text('}')
+
+class table_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REPLY
+    stats_type = const.OFPST_TABLE
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.entries]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = table_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_TABLE)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.entries = loxi.generic_util.unpack_list(reader, common.table_stats_entry.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.entries != other.entries: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("entries = ");
+                q.pp(self.entries)
+            q.breakable()
+        q.text('}')
+
+class table_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_STATS_REQUEST
+    stats_type = const.OFPST_TABLE
+
+    def __init__(self, xid=None, flags=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = table_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_STATS_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == const.OFPST_TABLE)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+            q.breakable()
+        q.text('}')
+
+
+def parse_header(buf):
+    if len(buf) < 8:
+        raise loxi.ProtocolError("too short to be an OpenFlow message")
+    return struct.unpack_from("!BBHL", buf)
+
+def parse_message(buf):
+    msg_ver, msg_type, msg_len, msg_xid = parse_header(buf)
+    if msg_ver != const.OFP_VERSION and msg_type != ofp.OFPT_HELLO:
+        raise loxi.ProtocolError("wrong OpenFlow version")
+    if len(buf) != msg_len:
+        raise loxi.ProtocolError("incorrect message size")
+    if msg_type in parsers:
+        return parsers[msg_type](buf)
+    else:
+        raise loxi.ProtocolError("unexpected message type")
+
+def parse_flow_mod(buf):
+    if len(buf) < 56 + 2:
+        raise loxi.ProtocolError("message too short")
+    cmd, = struct.unpack_from("!H", buf, 56)
+    if cmd in flow_mod_parsers:
+        return flow_mod_parsers[cmd](buf)
+    else:
+        raise loxi.ProtocolError("unexpected flow mod cmd %u" % cmd)
+
+def parse_stats_reply(buf):
+    if len(buf) < 8 + 2:
+        raise loxi.ProtocolError("message too short")
+    stats_type, = struct.unpack_from("!H", buf, 8)
+    if stats_type in stats_reply_parsers:
+        return stats_reply_parsers[stats_type](buf)
+    else:
+        raise loxi.ProtocolError("unexpected stats type %u" % stats_type)
+
+def parse_stats_request(buf):
+    if len(buf) < 8 + 2:
+        raise loxi.ProtocolError("message too short")
+    stats_type, = struct.unpack_from("!H", buf, 8)
+    if stats_type in stats_request_parsers:
+        return stats_request_parsers[stats_type](buf)
+    else:
+        raise loxi.ProtocolError("unexpected stats type %u" % stats_type)
+
+def parse_experimenter(buf):
+    if len(buf) < 16:
+        raise loxi.ProtocolError("experimenter message too short")
+
+    experimenter, = struct.unpack_from("!L", buf, 8)
+    if experimenter == 0x005c16c7: # Big Switch Networks
+        subtype, = struct.unpack_from("!L", buf, 12)
+    elif experimenter == 0x00002320: # Nicira
+        subtype, = struct.unpack_from("!L", buf, 12)
+    else:
+        raise loxi.ProtocolError("unexpected experimenter id %#x" % experimenter)
+
+    if subtype in experimenter_parsers[experimenter]:
+        return experimenter_parsers[experimenter][subtype](buf)
+    else:
+        raise loxi.ProtocolError("unexpected experimenter %#x subtype %#x" % (experimenter, subtype))
+
+parsers = {
+    const.OFPT_BARRIER_REPLY : barrier_reply.unpack,
+    const.OFPT_BARRIER_REQUEST : barrier_request.unpack,
+    const.OFPT_ECHO_REPLY : echo_reply.unpack,
+    const.OFPT_ECHO_REQUEST : echo_request.unpack,
+    const.OFPT_ERROR : error_msg.unpack,
+    const.OFPT_EXPERIMENTER : parse_experimenter,
+    const.OFPT_FEATURES_REPLY : features_reply.unpack,
+    const.OFPT_FEATURES_REQUEST : features_request.unpack,
+    const.OFPT_FLOW_MOD : parse_flow_mod,
+    const.OFPT_FLOW_REMOVED : flow_removed.unpack,
+    const.OFPT_GET_CONFIG_REPLY : get_config_reply.unpack,
+    const.OFPT_GET_CONFIG_REQUEST : get_config_request.unpack,
+    const.OFPT_GROUP_MOD : group_mod.unpack,
+    const.OFPT_HELLO : hello.unpack,
+    const.OFPT_PACKET_IN : packet_in.unpack,
+    const.OFPT_PACKET_OUT : packet_out.unpack,
+    const.OFPT_PORT_MOD : port_mod.unpack,
+    const.OFPT_PORT_STATUS : port_status.unpack,
+    const.OFPT_QUEUE_GET_CONFIG_REPLY : queue_get_config_reply.unpack,
+    const.OFPT_QUEUE_GET_CONFIG_REQUEST : queue_get_config_request.unpack,
+    const.OFPT_ROLE_REPLY : role_reply.unpack,
+    const.OFPT_ROLE_REQUEST : role_request.unpack,
+    const.OFPT_SET_CONFIG : set_config.unpack,
+    const.OFPT_STATS_REPLY : parse_stats_reply,
+    const.OFPT_STATS_REQUEST : parse_stats_request,
+    const.OFPT_TABLE_MOD : table_mod.unpack,
+}
+
+flow_mod_parsers = {
+    const.OFPFC_ADD : flow_add.unpack,
+    const.OFPFC_MODIFY : flow_modify.unpack,
+    const.OFPFC_MODIFY_STRICT : flow_modify_strict.unpack,
+    const.OFPFC_DELETE : flow_delete.unpack,
+    const.OFPFC_DELETE_STRICT : flow_delete_strict.unpack,
+}
+
+stats_reply_parsers = {
+    const.OFPST_DESC : desc_stats_reply.unpack,
+    const.OFPST_FLOW : flow_stats_reply.unpack,
+    const.OFPST_AGGREGATE : aggregate_stats_reply.unpack,
+    const.OFPST_TABLE : table_stats_reply.unpack,
+    const.OFPST_PORT : port_stats_reply.unpack,
+    const.OFPST_QUEUE : queue_stats_reply.unpack,
+    const.OFPST_EXPERIMENTER : experimenter_stats_reply.unpack,
+}
+
+stats_request_parsers = {
+    const.OFPST_DESC : desc_stats_request.unpack,
+    const.OFPST_FLOW : flow_stats_request.unpack,
+    const.OFPST_AGGREGATE : aggregate_stats_request.unpack,
+    const.OFPST_TABLE : table_stats_request.unpack,
+    const.OFPST_PORT : port_stats_request.unpack,
+    const.OFPST_QUEUE : queue_stats_request.unpack,
+    const.OFPST_EXPERIMENTER : experimenter_stats_request.unpack,
+}
+
+experimenter_parsers = {
+}
diff --git a/src/python/loxi/of12/oxm.py b/src/python/loxi/of12/oxm.py
new file mode 100644
index 0000000..d3bc046
--- /dev/null
+++ b/src/python/loxi/of12/oxm.py
@@ -0,0 +1,3990 @@
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+
+# Automatically generated by LOXI from template oxm.py
+# Do not modify
+
+import struct
+import const
+import util
+import loxi.generic_util
+import loxi
+
+def unpack_list(reader):
+    def deserializer(reader):
+        type_len, = reader.peek('!L')
+        if type_len in parsers:
+            return parsers[type_len](reader)
+        else:
+            raise loxi.ProtocolError("unknown OXM cls=%#x type=%#x masked=%d len=%d (%#x)" % \
+                ((type_len >> 16) & 0xffff, (type_len >> 9) & 0x7f, (type_len >> 8) & 1, type_len & 0xff, type_len))
+    return loxi.generic_util.unpack_list(reader, deserializer)
+
+class OXM(object):
+    type_len = None # override in subclass
+    pass
+
+class arp_op(OXM):
+    type_len = 0x80002a02
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = arp_op()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002a02)
+        obj.value = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("arp_op {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class arp_op_masked(OXM):
+    type_len = 0x80002b04
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        packed.append(struct.pack("!H", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = arp_op_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002b04)
+        obj.value = reader.read('!H')[0]
+        obj.value_mask = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("arp_op_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class arp_sha(OXM):
+    type_len = 0x80003006
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = [0,0,0,0,0,0]
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!6B", *self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = arp_sha()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003006)
+        obj.value = list(reader.read('!6B'))
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("arp_sha {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_mac(self.value))
+            q.breakable()
+        q.text('}')
+
+class arp_sha_masked(OXM):
+    type_len = 0x8000310c
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = [0,0,0,0,0,0]
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = [0,0,0,0,0,0]
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!6B", *self.value))
+        packed.append(struct.pack("!6B", *self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = arp_sha_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x8000310c)
+        obj.value = list(reader.read('!6B'))
+        obj.value_mask = list(reader.read('!6B'))
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("arp_sha_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_mac(self.value))
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text(util.pretty_mac(self.value_mask))
+            q.breakable()
+        q.text('}')
+
+class arp_spa(OXM):
+    type_len = 0x80002c04
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = arp_spa()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002c04)
+        obj.value = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("arp_spa {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class arp_spa_masked(OXM):
+    type_len = 0x80002d08
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        packed.append(struct.pack("!L", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = arp_spa_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002d08)
+        obj.value = reader.read('!L')[0]
+        obj.value_mask = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("arp_spa_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class arp_tha(OXM):
+    type_len = 0x80003206
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = [0,0,0,0,0,0]
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!6B", *self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = arp_tha()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003206)
+        obj.value = list(reader.read('!6B'))
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("arp_tha {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_mac(self.value))
+            q.breakable()
+        q.text('}')
+
+class arp_tha_masked(OXM):
+    type_len = 0x8000330c
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = [0,0,0,0,0,0]
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = [0,0,0,0,0,0]
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!6B", *self.value))
+        packed.append(struct.pack("!6B", *self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = arp_tha_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x8000330c)
+        obj.value = list(reader.read('!6B'))
+        obj.value_mask = list(reader.read('!6B'))
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("arp_tha_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_mac(self.value))
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text(util.pretty_mac(self.value_mask))
+            q.breakable()
+        q.text('}')
+
+class arp_tpa(OXM):
+    type_len = 0x80002e04
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = arp_tpa()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002e04)
+        obj.value = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("arp_tpa {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class arp_tpa_masked(OXM):
+    type_len = 0x80002f08
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        packed.append(struct.pack("!L", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = arp_tpa_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002f08)
+        obj.value = reader.read('!L')[0]
+        obj.value_mask = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("arp_tpa_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class eth_dst(OXM):
+    type_len = 0x80000606
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = [0,0,0,0,0,0]
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!6B", *self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = eth_dst()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000606)
+        obj.value = list(reader.read('!6B'))
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("eth_dst {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_mac(self.value))
+            q.breakable()
+        q.text('}')
+
+class eth_dst_masked(OXM):
+    type_len = 0x8000070c
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = [0,0,0,0,0,0]
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = [0,0,0,0,0,0]
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!6B", *self.value))
+        packed.append(struct.pack("!6B", *self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = eth_dst_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x8000070c)
+        obj.value = list(reader.read('!6B'))
+        obj.value_mask = list(reader.read('!6B'))
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("eth_dst_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_mac(self.value))
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text(util.pretty_mac(self.value_mask))
+            q.breakable()
+        q.text('}')
+
+class eth_src(OXM):
+    type_len = 0x80000806
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = [0,0,0,0,0,0]
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!6B", *self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = eth_src()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000806)
+        obj.value = list(reader.read('!6B'))
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("eth_src {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_mac(self.value))
+            q.breakable()
+        q.text('}')
+
+class eth_src_masked(OXM):
+    type_len = 0x8000090c
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = [0,0,0,0,0,0]
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = [0,0,0,0,0,0]
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!6B", *self.value))
+        packed.append(struct.pack("!6B", *self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = eth_src_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x8000090c)
+        obj.value = list(reader.read('!6B'))
+        obj.value_mask = list(reader.read('!6B'))
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("eth_src_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_mac(self.value))
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text(util.pretty_mac(self.value_mask))
+            q.breakable()
+        q.text('}')
+
+class eth_type(OXM):
+    type_len = 0x80000a02
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = eth_type()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000a02)
+        obj.value = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("eth_type {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class eth_type_masked(OXM):
+    type_len = 0x80000b04
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        packed.append(struct.pack("!H", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = eth_type_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000b04)
+        obj.value = reader.read('!H')[0]
+        obj.value_mask = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("eth_type_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class icmpv4_code(OXM):
+    type_len = 0x80002801
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = icmpv4_code()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002801)
+        obj.value = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("icmpv4_code {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class icmpv4_code_masked(OXM):
+    type_len = 0x80002902
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        packed.append(struct.pack("!B", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = icmpv4_code_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002902)
+        obj.value = reader.read('!B')[0]
+        obj.value_mask = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("icmpv4_code_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class icmpv4_type(OXM):
+    type_len = 0x80002601
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = icmpv4_type()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002601)
+        obj.value = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("icmpv4_type {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class icmpv4_type_masked(OXM):
+    type_len = 0x80002702
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        packed.append(struct.pack("!B", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = icmpv4_type_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002702)
+        obj.value = reader.read('!B')[0]
+        obj.value_mask = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("icmpv4_type_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class icmpv6_code(OXM):
+    type_len = 0x80003c01
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = icmpv6_code()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003c01)
+        obj.value = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("icmpv6_code {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class icmpv6_code_masked(OXM):
+    type_len = 0x80003d02
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        packed.append(struct.pack("!B", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = icmpv6_code_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003d02)
+        obj.value = reader.read('!B')[0]
+        obj.value_mask = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("icmpv6_code_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class icmpv6_type(OXM):
+    type_len = 0x80003a01
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = icmpv6_type()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003a01)
+        obj.value = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("icmpv6_type {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class icmpv6_type_masked(OXM):
+    type_len = 0x80003b02
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        packed.append(struct.pack("!B", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = icmpv6_type_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003b02)
+        obj.value = reader.read('!B')[0]
+        obj.value_mask = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("icmpv6_type_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class in_phy_port(OXM):
+    type_len = 0x80000204
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = in_phy_port()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000204)
+        obj.value = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("in_phy_port {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_port(self.value))
+            q.breakable()
+        q.text('}')
+
+class in_phy_port_masked(OXM):
+    type_len = 0x80000308
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        packed.append(struct.pack("!L", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = in_phy_port_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000308)
+        obj.value = reader.read('!L')[0]
+        obj.value_mask = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("in_phy_port_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_port(self.value))
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text(util.pretty_port(self.value_mask))
+            q.breakable()
+        q.text('}')
+
+class in_port(OXM):
+    type_len = 0x80000004
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = in_port()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000004)
+        obj.value = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("in_port {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_port(self.value))
+            q.breakable()
+        q.text('}')
+
+class in_port_masked(OXM):
+    type_len = 0x80000108
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        packed.append(struct.pack("!L", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = in_port_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000108)
+        obj.value = reader.read('!L')[0]
+        obj.value_mask = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("in_port_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_port(self.value))
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text(util.pretty_port(self.value_mask))
+            q.breakable()
+        q.text('}')
+
+class ip_dscp(OXM):
+    type_len = 0x80001001
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ip_dscp()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001001)
+        obj.value = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ip_dscp {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class ip_dscp_masked(OXM):
+    type_len = 0x80001102
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        packed.append(struct.pack("!B", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ip_dscp_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001102)
+        obj.value = reader.read('!B')[0]
+        obj.value_mask = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ip_dscp_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class ip_ecn(OXM):
+    type_len = 0x80001201
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ip_ecn()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001201)
+        obj.value = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ip_ecn {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class ip_ecn_masked(OXM):
+    type_len = 0x80001302
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        packed.append(struct.pack("!B", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ip_ecn_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001302)
+        obj.value = reader.read('!B')[0]
+        obj.value_mask = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ip_ecn_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class ip_proto(OXM):
+    type_len = 0x80001401
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ip_proto()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001401)
+        obj.value = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ip_proto {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class ip_proto_masked(OXM):
+    type_len = 0x80001502
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        packed.append(struct.pack("!B", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ip_proto_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001502)
+        obj.value = reader.read('!B')[0]
+        obj.value_mask = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ip_proto_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class ipv4_dst(OXM):
+    type_len = 0x80001804
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv4_dst()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001804)
+        obj.value = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv4_dst {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class ipv4_dst_masked(OXM):
+    type_len = 0x80001908
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        packed.append(struct.pack("!L", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv4_dst_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001908)
+        obj.value = reader.read('!L')[0]
+        obj.value_mask = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv4_dst_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class ipv4_src(OXM):
+    type_len = 0x80001604
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv4_src()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001604)
+        obj.value = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv4_src {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class ipv4_src_masked(OXM):
+    type_len = 0x80001708
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        packed.append(struct.pack("!L", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv4_src_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001708)
+        obj.value = reader.read('!L')[0]
+        obj.value_mask = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv4_src_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class ipv6_dst(OXM):
+    type_len = 0x80003610
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!16s", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv6_dst()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003610)
+        obj.value = reader.read('!16s')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv6_dst {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.pp(self.value)
+            q.breakable()
+        q.text('}')
+
+class ipv6_dst_masked(OXM):
+    type_len = 0x80003720
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!16s", self.value))
+        packed.append(struct.pack("!16s", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv6_dst_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003720)
+        obj.value = reader.read('!16s')[0]
+        obj.value_mask = reader.read('!16s')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv6_dst_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.pp(self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.pp(self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class ipv6_flabel(OXM):
+    type_len = 0x80003804
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv6_flabel()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003804)
+        obj.value = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv6_flabel {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class ipv6_flabel_masked(OXM):
+    type_len = 0x80003908
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        packed.append(struct.pack("!L", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv6_flabel_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003908)
+        obj.value = reader.read('!L')[0]
+        obj.value_mask = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv6_flabel_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class ipv6_nd_sll(OXM):
+    type_len = 0x80004006
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = [0,0,0,0,0,0]
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!6B", *self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv6_nd_sll()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80004006)
+        obj.value = list(reader.read('!6B'))
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv6_nd_sll {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_mac(self.value))
+            q.breakable()
+        q.text('}')
+
+class ipv6_nd_sll_masked(OXM):
+    type_len = 0x8000410c
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = [0,0,0,0,0,0]
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = [0,0,0,0,0,0]
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!6B", *self.value))
+        packed.append(struct.pack("!6B", *self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv6_nd_sll_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x8000410c)
+        obj.value = list(reader.read('!6B'))
+        obj.value_mask = list(reader.read('!6B'))
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv6_nd_sll_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_mac(self.value))
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text(util.pretty_mac(self.value_mask))
+            q.breakable()
+        q.text('}')
+
+class ipv6_nd_target(OXM):
+    type_len = 0x80003e10
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!16s", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv6_nd_target()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003e10)
+        obj.value = reader.read('!16s')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv6_nd_target {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.pp(self.value)
+            q.breakable()
+        q.text('}')
+
+class ipv6_nd_target_masked(OXM):
+    type_len = 0x80003f20
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!16s", self.value))
+        packed.append(struct.pack("!16s", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv6_nd_target_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003f20)
+        obj.value = reader.read('!16s')[0]
+        obj.value_mask = reader.read('!16s')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv6_nd_target_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.pp(self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.pp(self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class ipv6_nd_tll(OXM):
+    type_len = 0x80004206
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = [0,0,0,0,0,0]
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!6B", *self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv6_nd_tll()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80004206)
+        obj.value = list(reader.read('!6B'))
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv6_nd_tll {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_mac(self.value))
+            q.breakable()
+        q.text('}')
+
+class ipv6_nd_tll_masked(OXM):
+    type_len = 0x8000430c
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = [0,0,0,0,0,0]
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = [0,0,0,0,0,0]
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!6B", *self.value))
+        packed.append(struct.pack("!6B", *self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv6_nd_tll_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x8000430c)
+        obj.value = list(reader.read('!6B'))
+        obj.value_mask = list(reader.read('!6B'))
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv6_nd_tll_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_mac(self.value))
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text(util.pretty_mac(self.value_mask))
+            q.breakable()
+        q.text('}')
+
+class ipv6_src(OXM):
+    type_len = 0x80003410
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!16s", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv6_src()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003410)
+        obj.value = reader.read('!16s')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv6_src {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.pp(self.value)
+            q.breakable()
+        q.text('}')
+
+class ipv6_src_masked(OXM):
+    type_len = 0x80003520
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!16s", self.value))
+        packed.append(struct.pack("!16s", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv6_src_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003520)
+        obj.value = reader.read('!16s')[0]
+        obj.value_mask = reader.read('!16s')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv6_src_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.pp(self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.pp(self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class metadata(OXM):
+    type_len = 0x80000408
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!Q", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = metadata()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000408)
+        obj.value = reader.read('!Q')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("metadata {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class metadata_masked(OXM):
+    type_len = 0x80000510
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!Q", self.value))
+        packed.append(struct.pack("!Q", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = metadata_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000510)
+        obj.value = reader.read('!Q')[0]
+        obj.value_mask = reader.read('!Q')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("metadata_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class mpls_label(OXM):
+    type_len = 0x80004404
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = mpls_label()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80004404)
+        obj.value = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("mpls_label {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class mpls_label_masked(OXM):
+    type_len = 0x80004508
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        packed.append(struct.pack("!L", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = mpls_label_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80004508)
+        obj.value = reader.read('!L')[0]
+        obj.value_mask = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("mpls_label_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class mpls_tc(OXM):
+    type_len = 0x80004601
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = mpls_tc()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80004601)
+        obj.value = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("mpls_tc {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class mpls_tc_masked(OXM):
+    type_len = 0x80004702
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        packed.append(struct.pack("!B", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = mpls_tc_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80004702)
+        obj.value = reader.read('!B')[0]
+        obj.value_mask = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("mpls_tc_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class sctp_dst(OXM):
+    type_len = 0x80002402
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = sctp_dst()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002402)
+        obj.value = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("sctp_dst {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class sctp_dst_masked(OXM):
+    type_len = 0x80002504
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        packed.append(struct.pack("!H", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = sctp_dst_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002504)
+        obj.value = reader.read('!H')[0]
+        obj.value_mask = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("sctp_dst_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class sctp_src(OXM):
+    type_len = 0x80002202
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = sctp_src()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002202)
+        obj.value = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("sctp_src {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class sctp_src_masked(OXM):
+    type_len = 0x80002304
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        packed.append(struct.pack("!H", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = sctp_src_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002304)
+        obj.value = reader.read('!H')[0]
+        obj.value_mask = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("sctp_src_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class tcp_dst(OXM):
+    type_len = 0x80001c02
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = tcp_dst()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001c02)
+        obj.value = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("tcp_dst {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class tcp_dst_masked(OXM):
+    type_len = 0x80001d04
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        packed.append(struct.pack("!H", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = tcp_dst_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001d04)
+        obj.value = reader.read('!H')[0]
+        obj.value_mask = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("tcp_dst_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class tcp_src(OXM):
+    type_len = 0x80001a02
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = tcp_src()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001a02)
+        obj.value = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("tcp_src {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class tcp_src_masked(OXM):
+    type_len = 0x80001b04
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        packed.append(struct.pack("!H", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = tcp_src_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001b04)
+        obj.value = reader.read('!H')[0]
+        obj.value_mask = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("tcp_src_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class udp_dst(OXM):
+    type_len = 0x80002002
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = udp_dst()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002002)
+        obj.value = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("udp_dst {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class udp_dst_masked(OXM):
+    type_len = 0x80002104
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        packed.append(struct.pack("!H", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = udp_dst_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002104)
+        obj.value = reader.read('!H')[0]
+        obj.value_mask = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("udp_dst_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class udp_src(OXM):
+    type_len = 0x80001e02
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = udp_src()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001e02)
+        obj.value = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("udp_src {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class udp_src_masked(OXM):
+    type_len = 0x80001f04
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        packed.append(struct.pack("!H", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = udp_src_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001f04)
+        obj.value = reader.read('!H')[0]
+        obj.value_mask = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("udp_src_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class vlan_pcp(OXM):
+    type_len = 0x80000e01
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = vlan_pcp()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000e01)
+        obj.value = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("vlan_pcp {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class vlan_pcp_masked(OXM):
+    type_len = 0x80000f02
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        packed.append(struct.pack("!B", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = vlan_pcp_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000f02)
+        obj.value = reader.read('!B')[0]
+        obj.value_mask = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("vlan_pcp_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class vlan_vid(OXM):
+    type_len = 0x80000c02
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = vlan_vid()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000c02)
+        obj.value = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("vlan_vid {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class vlan_vid_masked(OXM):
+    type_len = 0x80000d04
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        packed.append(struct.pack("!H", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = vlan_vid_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000d04)
+        obj.value = reader.read('!H')[0]
+        obj.value_mask = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("vlan_vid_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+
+parsers = {
+    2147483652 : in_port.unpack,
+    2147483912 : in_port_masked.unpack,
+    2147484164 : in_phy_port.unpack,
+    2147484424 : in_phy_port_masked.unpack,
+    2147484680 : metadata.unpack,
+    2147484944 : metadata_masked.unpack,
+    2147485190 : eth_dst.unpack,
+    2147485452 : eth_dst_masked.unpack,
+    2147485702 : eth_src.unpack,
+    2147485964 : eth_src_masked.unpack,
+    2147486210 : eth_type.unpack,
+    2147486468 : eth_type_masked.unpack,
+    2147486722 : vlan_vid.unpack,
+    2147486980 : vlan_vid_masked.unpack,
+    2147487233 : vlan_pcp.unpack,
+    2147487490 : vlan_pcp_masked.unpack,
+    2147487745 : ip_dscp.unpack,
+    2147488002 : ip_dscp_masked.unpack,
+    2147488257 : ip_ecn.unpack,
+    2147488514 : ip_ecn_masked.unpack,
+    2147488769 : ip_proto.unpack,
+    2147489026 : ip_proto_masked.unpack,
+    2147489284 : ipv4_src.unpack,
+    2147489544 : ipv4_src_masked.unpack,
+    2147489796 : ipv4_dst.unpack,
+    2147490056 : ipv4_dst_masked.unpack,
+    2147490306 : tcp_src.unpack,
+    2147490564 : tcp_src_masked.unpack,
+    2147490818 : tcp_dst.unpack,
+    2147491076 : tcp_dst_masked.unpack,
+    2147491330 : udp_src.unpack,
+    2147491588 : udp_src_masked.unpack,
+    2147491842 : udp_dst.unpack,
+    2147492100 : udp_dst_masked.unpack,
+    2147492354 : sctp_src.unpack,
+    2147492612 : sctp_src_masked.unpack,
+    2147492866 : sctp_dst.unpack,
+    2147493124 : sctp_dst_masked.unpack,
+    2147493377 : icmpv4_type.unpack,
+    2147493634 : icmpv4_type_masked.unpack,
+    2147493889 : icmpv4_code.unpack,
+    2147494146 : icmpv4_code_masked.unpack,
+    2147494402 : arp_op.unpack,
+    2147494660 : arp_op_masked.unpack,
+    2147494916 : arp_spa.unpack,
+    2147495176 : arp_spa_masked.unpack,
+    2147495428 : arp_tpa.unpack,
+    2147495688 : arp_tpa_masked.unpack,
+    2147495942 : arp_sha.unpack,
+    2147496204 : arp_sha_masked.unpack,
+    2147496454 : arp_tha.unpack,
+    2147496716 : arp_tha_masked.unpack,
+    2147496976 : ipv6_src.unpack,
+    2147497248 : ipv6_src_masked.unpack,
+    2147497488 : ipv6_dst.unpack,
+    2147497760 : ipv6_dst_masked.unpack,
+    2147497988 : ipv6_flabel.unpack,
+    2147498248 : ipv6_flabel_masked.unpack,
+    2147498497 : icmpv6_type.unpack,
+    2147498754 : icmpv6_type_masked.unpack,
+    2147499009 : icmpv6_code.unpack,
+    2147499266 : icmpv6_code_masked.unpack,
+    2147499536 : ipv6_nd_target.unpack,
+    2147499808 : ipv6_nd_target_masked.unpack,
+    2147500038 : ipv6_nd_sll.unpack,
+    2147500300 : ipv6_nd_sll_masked.unpack,
+    2147500550 : ipv6_nd_tll.unpack,
+    2147500812 : ipv6_nd_tll_masked.unpack,
+    2147501060 : mpls_label.unpack,
+    2147501320 : mpls_label_masked.unpack,
+    2147501569 : mpls_tc.unpack,
+    2147501826 : mpls_tc_masked.unpack,
+}
diff --git a/src/python/loxi/of12/util.py b/src/python/loxi/of12/util.py
new file mode 100644
index 0000000..d431d4c
--- /dev/null
+++ b/src/python/loxi/of12/util.py
@@ -0,0 +1,37 @@
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+
+# Automatically generated by LOXI from template util.py
+# Do not modify
+
+import loxi
+import const
+import struct
+
+def pretty_mac(mac):
+    return ':'.join(["%02x" % x for x in mac])
+
+def pretty_ipv4(v):
+    return "%d.%d.%d.%d" % ((v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF)
+
+def pretty_flags(v, flag_names):
+    set_flags = []
+    for flag_name in flag_names:
+        flag_value = getattr(const, flag_name)
+        if v & flag_value == flag_value:
+            set_flags.append(flag_name)
+        elif v & flag_value:
+            set_flags.append('%s&%#x' % (flag_name, v & flag_value))
+        v &= ~flag_value
+    if v:
+        set_flags.append("%#x" % v)
+    return '|'.join(set_flags) or '0'
+
+
+def pretty_port(v):
+    named_ports = [(k,v2) for (k,v2) in const.__dict__.iteritems() if k.startswith('OFPP_')]
+    for (k, v2) in named_ports:
+        if v == v2:
+            return k
+    return v
diff --git a/src/python/loxi/of13/__init__.py b/src/python/loxi/of13/__init__.py
new file mode 100644
index 0000000..48364b1
--- /dev/null
+++ b/src/python/loxi/of13/__init__.py
@@ -0,0 +1,14 @@
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+
+# Automatically generated by LOXI from template init.py
+# Do not modify
+
+import action, common, const, message
+import instruction
+import oxm
+import meter_band
+from const import *
+from common import *
+from loxi import ProtocolError
diff --git a/src/python/loxi/of13/action.py b/src/python/loxi/of13/action.py
new file mode 100644
index 0000000..2a0629c
--- /dev/null
+++ b/src/python/loxi/of13/action.py
@@ -0,0 +1,1111 @@
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+
+# Automatically generated by LOXI from template action.py
+# Do not modify
+
+import struct
+import const
+import util
+import loxi.generic_util
+import loxi
+
+def unpack_list(reader):
+    def deserializer(reader, typ):
+        parser = parsers.get(typ)
+        if not parser: raise loxi.ProtocolError("unknown action type %d" % typ)
+        return parser(reader)
+    return loxi.generic_util.unpack_list_tlv16(reader, deserializer)
+
+class Action(object):
+    type = None # override in subclass
+    pass
+
+class bsn_mirror(Action):
+    type = const.OFPAT_EXPERIMENTER
+    experimenter = 0x5c16c7
+    subtype = 1
+
+    def __init__(self, dest_port=None, vlan_tag=None, copy_stage=None):
+        if dest_port != None:
+            self.dest_port = dest_port
+        else:
+            self.dest_port = 0
+        if vlan_tag != None:
+            self.vlan_tag = vlan_tag
+        else:
+            self.vlan_tag = 0
+        if copy_stage != None:
+            self.copy_stage = copy_stage
+        else:
+            self.copy_stage = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        packed.append(struct.pack("!L", self.dest_port))
+        packed.append(struct.pack("!L", self.vlan_tag))
+        packed.append(struct.pack("!B", self.copy_stage))
+        packed.append('\x00' * 3)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = bsn_mirror()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_EXPERIMENTER)
+        _len = reader.read('!H')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 1)
+        obj.dest_port = reader.read('!L')[0]
+        obj.vlan_tag = reader.read('!L')[0]
+        obj.copy_stage = reader.read('!B')[0]
+        reader.skip(3)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.dest_port != other.dest_port: return False
+        if self.vlan_tag != other.vlan_tag: return False
+        if self.copy_stage != other.copy_stage: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_mirror {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("dest_port = ");
+                q.text("%#x" % self.dest_port)
+                q.text(","); q.breakable()
+                q.text("vlan_tag = ");
+                q.text("%#x" % self.vlan_tag)
+                q.text(","); q.breakable()
+                q.text("copy_stage = ");
+                q.text("%#x" % self.copy_stage)
+            q.breakable()
+        q.text('}')
+
+class bsn_set_tunnel_dst(Action):
+    type = const.OFPAT_EXPERIMENTER
+    experimenter = 0x5c16c7
+    subtype = 2
+
+    def __init__(self, dst=None):
+        if dst != None:
+            self.dst = dst
+        else:
+            self.dst = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        packed.append(struct.pack("!L", self.dst))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = bsn_set_tunnel_dst()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_EXPERIMENTER)
+        _len = reader.read('!H')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 2)
+        obj.dst = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.dst != other.dst: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_set_tunnel_dst {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("dst = ");
+                q.text("%#x" % self.dst)
+            q.breakable()
+        q.text('}')
+
+class copy_ttl_in(Action):
+    type = const.OFPAT_COPY_TTL_IN
+
+    def __init__(self):
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = copy_ttl_in()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_COPY_TTL_IN)
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("copy_ttl_in {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+            q.breakable()
+        q.text('}')
+
+class copy_ttl_out(Action):
+    type = const.OFPAT_COPY_TTL_OUT
+
+    def __init__(self):
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = copy_ttl_out()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_COPY_TTL_OUT)
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("copy_ttl_out {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+            q.breakable()
+        q.text('}')
+
+class dec_mpls_ttl(Action):
+    type = const.OFPAT_DEC_MPLS_TTL
+
+    def __init__(self):
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = dec_mpls_ttl()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_DEC_MPLS_TTL)
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("dec_mpls_ttl {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+            q.breakable()
+        q.text('}')
+
+class dec_nw_ttl(Action):
+    type = const.OFPAT_DEC_NW_TTL
+
+    def __init__(self):
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = dec_nw_ttl()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_DEC_NW_TTL)
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("dec_nw_ttl {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+            q.breakable()
+        q.text('}')
+
+class group(Action):
+    type = const.OFPAT_GROUP
+
+    def __init__(self, group_id=None):
+        if group_id != None:
+            self.group_id = group_id
+        else:
+            self.group_id = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!L", self.group_id))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = group()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_GROUP)
+        _len = reader.read('!H')[0]
+        obj.group_id = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.group_id != other.group_id: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("group_id = ");
+                q.text("%#x" % self.group_id)
+            q.breakable()
+        q.text('}')
+
+class nicira_dec_ttl(Action):
+    type = const.OFPAT_EXPERIMENTER
+    experimenter = 0x2320
+    subtype = 18
+
+    def __init__(self):
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!H", self.subtype))
+        packed.append('\x00' * 2)
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = nicira_dec_ttl()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_EXPERIMENTER)
+        _len = reader.read('!H')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x2320)
+        _subtype = reader.read('!H')[0]
+        assert(_subtype == 18)
+        reader.skip(2)
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("nicira_dec_ttl {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+            q.breakable()
+        q.text('}')
+
+class output(Action):
+    type = const.OFPAT_OUTPUT
+
+    def __init__(self, port=None, max_len=None):
+        if port != None:
+            self.port = port
+        else:
+            self.port = 0
+        if max_len != None:
+            self.max_len = max_len
+        else:
+            self.max_len = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!L", self.port))
+        packed.append(struct.pack("!H", self.max_len))
+        packed.append('\x00' * 6)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = output()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_OUTPUT)
+        _len = reader.read('!H')[0]
+        obj.port = reader.read('!L')[0]
+        obj.max_len = reader.read('!H')[0]
+        reader.skip(6)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.port != other.port: return False
+        if self.max_len != other.max_len: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("output {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("port = ");
+                q.text(util.pretty_port(self.port))
+                q.text(","); q.breakable()
+                q.text("max_len = ");
+                q.text("%#x" % self.max_len)
+            q.breakable()
+        q.text('}')
+
+class pop_mpls(Action):
+    type = const.OFPAT_POP_MPLS
+
+    def __init__(self, ethertype=None):
+        if ethertype != None:
+            self.ethertype = ethertype
+        else:
+            self.ethertype = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!H", self.ethertype))
+        packed.append('\x00' * 2)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = pop_mpls()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_POP_MPLS)
+        _len = reader.read('!H')[0]
+        obj.ethertype = reader.read('!H')[0]
+        reader.skip(2)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.ethertype != other.ethertype: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("pop_mpls {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("ethertype = ");
+                q.text("%#x" % self.ethertype)
+            q.breakable()
+        q.text('}')
+
+class pop_pbb(Action):
+    type = const.OFPAT_POP_PBB
+
+    def __init__(self):
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = pop_pbb()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_POP_PBB)
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("pop_pbb {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+            q.breakable()
+        q.text('}')
+
+class pop_vlan(Action):
+    type = const.OFPAT_POP_VLAN
+
+    def __init__(self):
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = pop_vlan()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_POP_VLAN)
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("pop_vlan {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+            q.breakable()
+        q.text('}')
+
+class push_mpls(Action):
+    type = const.OFPAT_PUSH_MPLS
+
+    def __init__(self, ethertype=None):
+        if ethertype != None:
+            self.ethertype = ethertype
+        else:
+            self.ethertype = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!H", self.ethertype))
+        packed.append('\x00' * 2)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = push_mpls()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_PUSH_MPLS)
+        _len = reader.read('!H')[0]
+        obj.ethertype = reader.read('!H')[0]
+        reader.skip(2)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.ethertype != other.ethertype: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("push_mpls {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("ethertype = ");
+                q.text("%#x" % self.ethertype)
+            q.breakable()
+        q.text('}')
+
+class push_pbb(Action):
+    type = const.OFPAT_PUSH_PBB
+
+    def __init__(self, ethertype=None):
+        if ethertype != None:
+            self.ethertype = ethertype
+        else:
+            self.ethertype = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!H", self.ethertype))
+        packed.append('\x00' * 2)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = push_pbb()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_PUSH_PBB)
+        _len = reader.read('!H')[0]
+        obj.ethertype = reader.read('!H')[0]
+        reader.skip(2)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.ethertype != other.ethertype: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("push_pbb {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("ethertype = ");
+                q.text("%#x" % self.ethertype)
+            q.breakable()
+        q.text('}')
+
+class push_vlan(Action):
+    type = const.OFPAT_PUSH_VLAN
+
+    def __init__(self, ethertype=None):
+        if ethertype != None:
+            self.ethertype = ethertype
+        else:
+            self.ethertype = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!H", self.ethertype))
+        packed.append('\x00' * 2)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = push_vlan()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_PUSH_VLAN)
+        _len = reader.read('!H')[0]
+        obj.ethertype = reader.read('!H')[0]
+        reader.skip(2)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.ethertype != other.ethertype: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("push_vlan {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("ethertype = ");
+                q.text("%#x" % self.ethertype)
+            q.breakable()
+        q.text('}')
+
+class set_field(Action):
+    type = const.OFPAT_SET_FIELD
+
+    def __init__(self, field=None):
+        if field != None:
+            self.field = field
+        else:
+            self.field = ""
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(self.field)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = set_field()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_FIELD)
+        _len = reader.read('!H')[0]
+        obj.field = str(reader.read_all())
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.field != other.field: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("set_field {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("field = ");
+                q.pp(self.field)
+            q.breakable()
+        q.text('}')
+
+class set_mpls_ttl(Action):
+    type = const.OFPAT_SET_MPLS_TTL
+
+    def __init__(self, mpls_ttl=None):
+        if mpls_ttl != None:
+            self.mpls_ttl = mpls_ttl
+        else:
+            self.mpls_ttl = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!B", self.mpls_ttl))
+        packed.append('\x00' * 3)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = set_mpls_ttl()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_MPLS_TTL)
+        _len = reader.read('!H')[0]
+        obj.mpls_ttl = reader.read('!B')[0]
+        reader.skip(3)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.mpls_ttl != other.mpls_ttl: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("set_mpls_ttl {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("mpls_ttl = ");
+                q.text("%#x" % self.mpls_ttl)
+            q.breakable()
+        q.text('}')
+
+class set_nw_ttl(Action):
+    type = const.OFPAT_SET_NW_TTL
+
+    def __init__(self, nw_ttl=None):
+        if nw_ttl != None:
+            self.nw_ttl = nw_ttl
+        else:
+            self.nw_ttl = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!B", self.nw_ttl))
+        packed.append('\x00' * 3)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = set_nw_ttl()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_NW_TTL)
+        _len = reader.read('!H')[0]
+        obj.nw_ttl = reader.read('!B')[0]
+        reader.skip(3)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.nw_ttl != other.nw_ttl: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("set_nw_ttl {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("nw_ttl = ");
+                q.text("%#x" % self.nw_ttl)
+            q.breakable()
+        q.text('}')
+
+class set_queue(Action):
+    type = const.OFPAT_SET_QUEUE
+
+    def __init__(self, queue_id=None):
+        if queue_id != None:
+            self.queue_id = queue_id
+        else:
+            self.queue_id = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!L", self.queue_id))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = set_queue()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPAT_SET_QUEUE)
+        _len = reader.read('!H')[0]
+        obj.queue_id = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.queue_id != other.queue_id: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("set_queue {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("queue_id = ");
+                q.text("%#x" % self.queue_id)
+            q.breakable()
+        q.text('}')
+
+
+def parse_experimenter(reader):
+
+    experimenter, = reader.peek("!4xL")
+    if experimenter == 0x005c16c7: # Big Switch Networks
+        subtype, = reader.peek("!8xL")
+    elif experimenter == 0x00002320: # Nicira
+        subtype, = reader.peek("!8xH")
+    else:
+        raise loxi.ProtocolError("unexpected experimenter id %#x" % experimenter)
+
+    if subtype in experimenter_parsers[experimenter]:
+        return experimenter_parsers[experimenter][subtype](reader)
+    else:
+        raise loxi.ProtocolError("unexpected BSN experimenter subtype %#x" % subtype)
+
+parsers = {
+    const.OFPAT_COPY_TTL_IN : copy_ttl_in.unpack,
+    const.OFPAT_COPY_TTL_OUT : copy_ttl_out.unpack,
+    const.OFPAT_DEC_MPLS_TTL : dec_mpls_ttl.unpack,
+    const.OFPAT_DEC_NW_TTL : dec_nw_ttl.unpack,
+    const.OFPAT_EXPERIMENTER : parse_experimenter,
+    const.OFPAT_GROUP : group.unpack,
+    const.OFPAT_OUTPUT : output.unpack,
+    const.OFPAT_POP_MPLS : pop_mpls.unpack,
+    const.OFPAT_POP_PBB : pop_pbb.unpack,
+    const.OFPAT_POP_VLAN : pop_vlan.unpack,
+    const.OFPAT_PUSH_MPLS : push_mpls.unpack,
+    const.OFPAT_PUSH_PBB : push_pbb.unpack,
+    const.OFPAT_PUSH_VLAN : push_vlan.unpack,
+    const.OFPAT_SET_FIELD : set_field.unpack,
+    const.OFPAT_SET_MPLS_TTL : set_mpls_ttl.unpack,
+    const.OFPAT_SET_NW_TTL : set_nw_ttl.unpack,
+    const.OFPAT_SET_QUEUE : set_queue.unpack,
+}
+
+experimenter_parsers = {
+}
diff --git a/src/python/loxi/of13/common.py b/src/python/loxi/of13/common.py
new file mode 100644
index 0000000..84572eb
--- /dev/null
+++ b/src/python/loxi/of13/common.py
@@ -0,0 +1,4051 @@
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+
+# Automatically generated by LOXI from template common.py
+# Do not modify
+
+import sys
+import struct
+import action
+import instruction # for unpack_list
+import meter_band # for unpack_list
+import const
+import util
+import loxi.generic_util
+
+import oxm
+
+# HACK make this module visible as 'common' to simplify code generation
+common = sys.modules[__name__]
+
+def unpack_list_flow_stats_entry(reader):
+    return loxi.generic_util.unpack_list_lv16(reader, flow_stats_entry.unpack)
+
+def unpack_list_queue_prop(reader):
+    def deserializer(reader, typ):
+        if typ == const.OFPQT_MIN_RATE:
+            return queue_prop_min_rate.unpack(reader)
+        else:
+            raise loxi.ProtocolError("unknown queue prop %d" % typ)
+    return loxi.generic_util.unpack_list_tlv16(reader, deserializer)
+
+def unpack_list_packet_queue(reader):
+    def wrapper(reader):
+        length, = reader.peek('!4xH')
+        return packet_queue.unpack(reader.slice(length))
+    return loxi.generic_util.unpack_list(reader, wrapper)
+
+def unpack_list_hello_elem(reader):
+    def deserializer(reader, typ):
+        if typ == const.OFPHET_VERSIONBITMAP:
+            return hello_elem_versionbitmap.unpack(reader)
+        else:
+            return None
+    return [x for x in loxi.generic_util.unpack_list_tlv16(reader, deserializer) if x != None]
+
+def unpack_list_bucket(reader):
+    return loxi.generic_util.unpack_list_lv16(reader, bucket.unpack)
+
+def unpack_list_group_desc_stats_entry(reader):
+    return loxi.generic_util.unpack_list_lv16(reader, group_desc_stats_entry.unpack)
+
+def unpack_list_group_stats_entry(reader):
+    return loxi.generic_util.unpack_list_lv16(reader, group_stats_entry.unpack)
+
+def unpack_list_meter_stats(reader):
+    def wrapper(reader):
+        length, = reader.peek('!4xH')
+        return meter_stats.unpack(reader.slice(length))
+    return loxi.generic_util.unpack_list(reader, wrapper)
+
+class action_id_bsn_mirror(object):
+
+    def __init__(self, type=None, experimenter=None, subtype=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        if experimenter != None:
+            self.experimenter = experimenter
+        else:
+            self.experimenter = 0
+        if subtype != None:
+            self.subtype = subtype
+        else:
+            self.subtype = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = action_id_bsn_mirror()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _len = reader.read('!H')[0]
+        obj.experimenter = reader.read('!L')[0]
+        obj.subtype = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        if self.experimenter != other.experimenter: return False
+        if self.subtype != other.subtype: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("action_id_bsn_mirror {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+                q.text(","); q.breakable()
+                q.text("experimenter = ");
+                q.text("%#x" % self.experimenter)
+                q.text(","); q.breakable()
+                q.text("subtype = ");
+                q.text("%#x" % self.subtype)
+            q.breakable()
+        q.text('}')
+
+class action_id_bsn_set_tunnel_dst(object):
+
+    def __init__(self, type=None, experimenter=None, subtype=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        if experimenter != None:
+            self.experimenter = experimenter
+        else:
+            self.experimenter = 0
+        if subtype != None:
+            self.subtype = subtype
+        else:
+            self.subtype = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = action_id_bsn_set_tunnel_dst()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _len = reader.read('!H')[0]
+        obj.experimenter = reader.read('!L')[0]
+        obj.subtype = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        if self.experimenter != other.experimenter: return False
+        if self.subtype != other.subtype: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("action_id_bsn_set_tunnel_dst {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+                q.text(","); q.breakable()
+                q.text("experimenter = ");
+                q.text("%#x" % self.experimenter)
+                q.text(","); q.breakable()
+                q.text("subtype = ");
+                q.text("%#x" % self.subtype)
+            q.breakable()
+        q.text('}')
+
+class action_id_copy_ttl_in(object):
+
+    def __init__(self, type=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = action_id_copy_ttl_in()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("action_id_copy_ttl_in {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+            q.breakable()
+        q.text('}')
+
+class action_id_copy_ttl_out(object):
+
+    def __init__(self, type=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = action_id_copy_ttl_out()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("action_id_copy_ttl_out {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+            q.breakable()
+        q.text('}')
+
+class action_id_dec_mpls_ttl(object):
+
+    def __init__(self, type=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = action_id_dec_mpls_ttl()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("action_id_dec_mpls_ttl {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+            q.breakable()
+        q.text('}')
+
+class action_id_dec_nw_ttl(object):
+
+    def __init__(self, type=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = action_id_dec_nw_ttl()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("action_id_dec_nw_ttl {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+            q.breakable()
+        q.text('}')
+
+class action_id_experimenter(object):
+
+    def __init__(self, type=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = action_id_experimenter()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("action_id_experimenter {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+            q.breakable()
+        q.text('}')
+
+class action_id_group(object):
+
+    def __init__(self, type=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = action_id_group()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("action_id_group {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+            q.breakable()
+        q.text('}')
+
+class action_id_nicira_dec_ttl(object):
+
+    def __init__(self, type=None, experimenter=None, subtype=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        if experimenter != None:
+            self.experimenter = experimenter
+        else:
+            self.experimenter = 0
+        if subtype != None:
+            self.subtype = subtype
+        else:
+            self.subtype = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!H", self.subtype))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = action_id_nicira_dec_ttl()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _len = reader.read('!H')[0]
+        obj.experimenter = reader.read('!L')[0]
+        obj.subtype = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        if self.experimenter != other.experimenter: return False
+        if self.subtype != other.subtype: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("action_id_nicira_dec_ttl {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+                q.text(","); q.breakable()
+                q.text("experimenter = ");
+                q.text("%#x" % self.experimenter)
+                q.text(","); q.breakable()
+                q.text("subtype = ");
+                q.text("%#x" % self.subtype)
+            q.breakable()
+        q.text('}')
+
+class action_id_output(object):
+
+    def __init__(self, type=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = action_id_output()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("action_id_output {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+            q.breakable()
+        q.text('}')
+
+class action_id_pop_mpls(object):
+
+    def __init__(self, type=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = action_id_pop_mpls()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("action_id_pop_mpls {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+            q.breakable()
+        q.text('}')
+
+class action_id_pop_pbb(object):
+
+    def __init__(self, type=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = action_id_pop_pbb()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("action_id_pop_pbb {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+            q.breakable()
+        q.text('}')
+
+class action_id_pop_vlan(object):
+
+    def __init__(self, type=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = action_id_pop_vlan()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("action_id_pop_vlan {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+            q.breakable()
+        q.text('}')
+
+class action_id_push_mpls(object):
+
+    def __init__(self, type=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = action_id_push_mpls()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("action_id_push_mpls {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+            q.breakable()
+        q.text('}')
+
+class action_id_push_pbb(object):
+
+    def __init__(self, type=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = action_id_push_pbb()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("action_id_push_pbb {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+            q.breakable()
+        q.text('}')
+
+class action_id_push_vlan(object):
+
+    def __init__(self, type=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = action_id_push_vlan()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("action_id_push_vlan {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+            q.breakable()
+        q.text('}')
+
+class action_id_set_field(object):
+
+    def __init__(self, type=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = action_id_set_field()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("action_id_set_field {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+            q.breakable()
+        q.text('}')
+
+class action_id_set_mpls_ttl(object):
+
+    def __init__(self, type=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = action_id_set_mpls_ttl()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("action_id_set_mpls_ttl {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+            q.breakable()
+        q.text('}')
+
+class action_id_set_nw_ttl(object):
+
+    def __init__(self, type=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = action_id_set_nw_ttl()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("action_id_set_nw_ttl {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+            q.breakable()
+        q.text('}')
+
+class action_id_set_queue(object):
+
+    def __init__(self, type=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = action_id_set_queue()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("action_id_set_queue {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+            q.breakable()
+        q.text('}')
+
+class bsn_interface(object):
+
+    def __init__(self, hw_addr=None, name=None, ipv4_addr=None, ipv4_netmask=None):
+        if hw_addr != None:
+            self.hw_addr = hw_addr
+        else:
+            self.hw_addr = [0,0,0,0,0,0]
+        if name != None:
+            self.name = name
+        else:
+            self.name = ""
+        if ipv4_addr != None:
+            self.ipv4_addr = ipv4_addr
+        else:
+            self.ipv4_addr = 0
+        if ipv4_netmask != None:
+            self.ipv4_netmask = ipv4_netmask
+        else:
+            self.ipv4_netmask = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!6B", *self.hw_addr))
+        packed.append('\x00' * 2)
+        packed.append(struct.pack("!16s", self.name))
+        packed.append(struct.pack("!L", self.ipv4_addr))
+        packed.append(struct.pack("!L", self.ipv4_netmask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = bsn_interface()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.hw_addr = list(reader.read('!6B'))
+        reader.skip(2)
+        obj.name = reader.read("!16s")[0].rstrip("\x00")
+        obj.ipv4_addr = reader.read('!L')[0]
+        obj.ipv4_netmask = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.hw_addr != other.hw_addr: return False
+        if self.name != other.name: return False
+        if self.ipv4_addr != other.ipv4_addr: return False
+        if self.ipv4_netmask != other.ipv4_netmask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_interface {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("hw_addr = ");
+                q.text(util.pretty_mac(self.hw_addr))
+                q.text(","); q.breakable()
+                q.text("name = ");
+                q.pp(self.name)
+                q.text(","); q.breakable()
+                q.text("ipv4_addr = ");
+                q.text(util.pretty_ipv4(self.ipv4_addr))
+                q.text(","); q.breakable()
+                q.text("ipv4_netmask = ");
+                q.text(util.pretty_ipv4(self.ipv4_netmask))
+            q.breakable()
+        q.text('}')
+
+class bucket(object):
+
+    def __init__(self, weight=None, watch_port=None, watch_group=None, actions=None):
+        if weight != None:
+            self.weight = weight
+        else:
+            self.weight = 0
+        if watch_port != None:
+            self.watch_port = watch_port
+        else:
+            self.watch_port = 0
+        if watch_group != None:
+            self.watch_group = watch_group
+        else:
+            self.watch_group = 0
+        if actions != None:
+            self.actions = actions
+        else:
+            self.actions = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 0
+        packed.append(struct.pack("!H", self.weight))
+        packed.append(struct.pack("!L", self.watch_port))
+        packed.append(struct.pack("!L", self.watch_group))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.actions]))
+        length = sum([len(x) for x in packed])
+        packed[0] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = bucket()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _len = reader.read('!H')[0]
+        obj.weight = reader.read('!H')[0]
+        obj.watch_port = reader.read('!L')[0]
+        obj.watch_group = reader.read('!L')[0]
+        reader.skip(4)
+        obj.actions = action.unpack_list(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.weight != other.weight: return False
+        if self.watch_port != other.watch_port: return False
+        if self.watch_group != other.watch_group: return False
+        if self.actions != other.actions: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bucket {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("weight = ");
+                q.text("%#x" % self.weight)
+                q.text(","); q.breakable()
+                q.text("watch_port = ");
+                q.text(util.pretty_port(self.watch_port))
+                q.text(","); q.breakable()
+                q.text("watch_group = ");
+                q.text("%#x" % self.watch_group)
+                q.text(","); q.breakable()
+                q.text("actions = ");
+                q.pp(self.actions)
+            q.breakable()
+        q.text('}')
+
+class bucket_counter(object):
+
+    def __init__(self, packet_count=None, byte_count=None):
+        if packet_count != None:
+            self.packet_count = packet_count
+        else:
+            self.packet_count = 0
+        if byte_count != None:
+            self.byte_count = byte_count
+        else:
+            self.byte_count = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!Q", self.packet_count))
+        packed.append(struct.pack("!Q", self.byte_count))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = bucket_counter()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.packet_count = reader.read('!Q')[0]
+        obj.byte_count = reader.read('!Q')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.packet_count != other.packet_count: return False
+        if self.byte_count != other.byte_count: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bucket_counter {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("packet_count = ");
+                q.text("%#x" % self.packet_count)
+                q.text(","); q.breakable()
+                q.text("byte_count = ");
+                q.text("%#x" % self.byte_count)
+            q.breakable()
+        q.text('}')
+
+class flow_stats_entry(object):
+
+    def __init__(self, table_id=None, duration_sec=None, duration_nsec=None, priority=None, idle_timeout=None, hard_timeout=None, cookie=None, packet_count=None, byte_count=None, match=None, instructions=None):
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if duration_sec != None:
+            self.duration_sec = duration_sec
+        else:
+            self.duration_sec = 0
+        if duration_nsec != None:
+            self.duration_nsec = duration_nsec
+        else:
+            self.duration_nsec = 0
+        if priority != None:
+            self.priority = priority
+        else:
+            self.priority = 0
+        if idle_timeout != None:
+            self.idle_timeout = idle_timeout
+        else:
+            self.idle_timeout = 0
+        if hard_timeout != None:
+            self.hard_timeout = hard_timeout
+        else:
+            self.hard_timeout = 0
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if packet_count != None:
+            self.packet_count = packet_count
+        else:
+            self.packet_count = 0
+        if byte_count != None:
+            self.byte_count = byte_count
+        else:
+            self.byte_count = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+        if instructions != None:
+            self.instructions = instructions
+        else:
+            self.instructions = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 0
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append('\x00' * 1)
+        packed.append(struct.pack("!L", self.duration_sec))
+        packed.append(struct.pack("!L", self.duration_nsec))
+        packed.append(struct.pack("!H", self.priority))
+        packed.append(struct.pack("!H", self.idle_timeout))
+        packed.append(struct.pack("!H", self.hard_timeout))
+        packed.append('\x00' * 6)
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!Q", self.packet_count))
+        packed.append(struct.pack("!Q", self.byte_count))
+        packed.append(self.match.pack())
+        packed.append("".join([x.pack() for x in self.instructions]))
+        length = sum([len(x) for x in packed])
+        packed[0] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = flow_stats_entry()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _length = reader.read('!H')[0]
+        obj.table_id = reader.read('!B')[0]
+        reader.skip(1)
+        obj.duration_sec = reader.read('!L')[0]
+        obj.duration_nsec = reader.read('!L')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        reader.skip(6)
+        obj.cookie = reader.read('!Q')[0]
+        obj.packet_count = reader.read('!Q')[0]
+        obj.byte_count = reader.read('!Q')[0]
+        obj.match = common.match.unpack(reader)
+        obj.instructions = instruction.unpack_list(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.table_id != other.table_id: return False
+        if self.duration_sec != other.duration_sec: return False
+        if self.duration_nsec != other.duration_nsec: return False
+        if self.priority != other.priority: return False
+        if self.idle_timeout != other.idle_timeout: return False
+        if self.hard_timeout != other.hard_timeout: return False
+        if self.cookie != other.cookie: return False
+        if self.packet_count != other.packet_count: return False
+        if self.byte_count != other.byte_count: return False
+        if self.match != other.match: return False
+        if self.instructions != other.instructions: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_stats_entry {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("duration_sec = ");
+                q.text("%#x" % self.duration_sec)
+                q.text(","); q.breakable()
+                q.text("duration_nsec = ");
+                q.text("%#x" % self.duration_nsec)
+                q.text(","); q.breakable()
+                q.text("priority = ");
+                q.text("%#x" % self.priority)
+                q.text(","); q.breakable()
+                q.text("idle_timeout = ");
+                q.text("%#x" % self.idle_timeout)
+                q.text(","); q.breakable()
+                q.text("hard_timeout = ");
+                q.text("%#x" % self.hard_timeout)
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("packet_count = ");
+                q.text("%#x" % self.packet_count)
+                q.text(","); q.breakable()
+                q.text("byte_count = ");
+                q.text("%#x" % self.byte_count)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+                q.text(","); q.breakable()
+                q.text("instructions = ");
+                q.pp(self.instructions)
+            q.breakable()
+        q.text('}')
+
+class group_desc_stats_entry(object):
+
+    def __init__(self, type=None, group_id=None, buckets=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        if group_id != None:
+            self.group_id = group_id
+        else:
+            self.group_id = 0
+        if buckets != None:
+            self.buckets = buckets
+        else:
+            self.buckets = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 0
+        packed.append(struct.pack("!B", self.type))
+        packed.append('\x00' * 1)
+        packed.append(struct.pack("!L", self.group_id))
+        packed.append("".join([x.pack() for x in self.buckets]))
+        length = sum([len(x) for x in packed])
+        packed[0] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = group_desc_stats_entry()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _length = reader.read('!H')[0]
+        obj.type = reader.read('!B')[0]
+        reader.skip(1)
+        obj.group_id = reader.read('!L')[0]
+        obj.buckets = common.unpack_list_bucket(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        if self.group_id != other.group_id: return False
+        if self.buckets != other.buckets: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group_desc_stats_entry {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+                q.text(","); q.breakable()
+                q.text("group_id = ");
+                q.text("%#x" % self.group_id)
+                q.text(","); q.breakable()
+                q.text("buckets = ");
+                q.pp(self.buckets)
+            q.breakable()
+        q.text('}')
+
+class group_stats_entry(object):
+
+    def __init__(self, group_id=None, ref_count=None, packet_count=None, byte_count=None, duration_sec=None, duration_nsec=None, bucket_stats=None):
+        if group_id != None:
+            self.group_id = group_id
+        else:
+            self.group_id = 0
+        if ref_count != None:
+            self.ref_count = ref_count
+        else:
+            self.ref_count = 0
+        if packet_count != None:
+            self.packet_count = packet_count
+        else:
+            self.packet_count = 0
+        if byte_count != None:
+            self.byte_count = byte_count
+        else:
+            self.byte_count = 0
+        if duration_sec != None:
+            self.duration_sec = duration_sec
+        else:
+            self.duration_sec = 0
+        if duration_nsec != None:
+            self.duration_nsec = duration_nsec
+        else:
+            self.duration_nsec = 0
+        if bucket_stats != None:
+            self.bucket_stats = bucket_stats
+        else:
+            self.bucket_stats = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 0
+        packed.append('\x00' * 2)
+        packed.append(struct.pack("!L", self.group_id))
+        packed.append(struct.pack("!L", self.ref_count))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!Q", self.packet_count))
+        packed.append(struct.pack("!Q", self.byte_count))
+        packed.append(struct.pack("!L", self.duration_sec))
+        packed.append(struct.pack("!L", self.duration_nsec))
+        packed.append("".join([x.pack() for x in self.bucket_stats]))
+        length = sum([len(x) for x in packed])
+        packed[0] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = group_stats_entry()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _length = reader.read('!H')[0]
+        reader.skip(2)
+        obj.group_id = reader.read('!L')[0]
+        obj.ref_count = reader.read('!L')[0]
+        reader.skip(4)
+        obj.packet_count = reader.read('!Q')[0]
+        obj.byte_count = reader.read('!Q')[0]
+        obj.duration_sec = reader.read('!L')[0]
+        obj.duration_nsec = reader.read('!L')[0]
+        obj.bucket_stats = loxi.generic_util.unpack_list(reader, common.bucket_counter.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.group_id != other.group_id: return False
+        if self.ref_count != other.ref_count: return False
+        if self.packet_count != other.packet_count: return False
+        if self.byte_count != other.byte_count: return False
+        if self.duration_sec != other.duration_sec: return False
+        if self.duration_nsec != other.duration_nsec: return False
+        if self.bucket_stats != other.bucket_stats: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group_stats_entry {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("group_id = ");
+                q.text("%#x" % self.group_id)
+                q.text(","); q.breakable()
+                q.text("ref_count = ");
+                q.text("%#x" % self.ref_count)
+                q.text(","); q.breakable()
+                q.text("packet_count = ");
+                q.text("%#x" % self.packet_count)
+                q.text(","); q.breakable()
+                q.text("byte_count = ");
+                q.text("%#x" % self.byte_count)
+                q.text(","); q.breakable()
+                q.text("duration_sec = ");
+                q.text("%#x" % self.duration_sec)
+                q.text(","); q.breakable()
+                q.text("duration_nsec = ");
+                q.text("%#x" % self.duration_nsec)
+                q.text(","); q.breakable()
+                q.text("bucket_stats = ");
+                q.pp(self.bucket_stats)
+            q.breakable()
+        q.text('}')
+
+class hello_elem_versionbitmap(object):
+    type = const.OFPHET_VERSIONBITMAP
+
+    def __init__(self, bitmaps=None):
+        if bitmaps != None:
+            self.bitmaps = bitmaps
+        else:
+            self.bitmaps = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 1
+        packed.append("".join([x.pack() for x in self.bitmaps]))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = hello_elem_versionbitmap()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPHET_VERSIONBITMAP)
+        _length = reader.read('!H')[0]
+        obj.bitmaps = loxi.generic_util.unpack_list(reader, common.uint32.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.bitmaps != other.bitmaps: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("hello_elem_versionbitmap {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("bitmaps = ");
+                q.pp(self.bitmaps)
+            q.breakable()
+        q.text('}')
+
+class match_v3(object):
+    type = 1
+
+    def __init__(self, oxm_list=None):
+        if oxm_list != None:
+            self.oxm_list = oxm_list
+        else:
+            self.oxm_list = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 1
+        packed.append("".join([x.pack() for x in self.oxm_list]))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        packed.append('\x00' * ((length + 7)/8*8 - length))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = match_v3()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == 1)
+        _length = reader.read('!H')[0]
+        obj.oxm_list = oxm.unpack_list(reader.slice(_length-4))
+        reader.skip((_length + 7)/8*8 - _length)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.oxm_list != other.oxm_list: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("match_v3 {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("oxm_list = ");
+                q.pp(self.oxm_list)
+            q.breakable()
+        q.text('}')
+
+class meter_band_stats(object):
+
+    def __init__(self, packet_band_count=None, byte_band_count=None):
+        if packet_band_count != None:
+            self.packet_band_count = packet_band_count
+        else:
+            self.packet_band_count = 0
+        if byte_band_count != None:
+            self.byte_band_count = byte_band_count
+        else:
+            self.byte_band_count = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!Q", self.packet_band_count))
+        packed.append(struct.pack("!Q", self.byte_band_count))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = meter_band_stats()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.packet_band_count = reader.read('!Q')[0]
+        obj.byte_band_count = reader.read('!Q')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.packet_band_count != other.packet_band_count: return False
+        if self.byte_band_count != other.byte_band_count: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("meter_band_stats {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("packet_band_count = ");
+                q.text("%#x" % self.packet_band_count)
+                q.text(","); q.breakable()
+                q.text("byte_band_count = ");
+                q.text("%#x" % self.byte_band_count)
+            q.breakable()
+        q.text('}')
+
+class meter_config(object):
+
+    def __init__(self, flags=None, meter_id=None, entries=None):
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if meter_id != None:
+            self.meter_id = meter_id
+        else:
+            self.meter_id = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 0
+        packed.append(struct.pack("!H", self.flags))
+        packed.append(struct.pack("!L", self.meter_id))
+        packed.append("".join([x.pack() for x in self.entries]))
+        length = sum([len(x) for x in packed])
+        packed[0] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = meter_config()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _length = reader.read('!H')[0]
+        obj.flags = reader.read('!H')[0]
+        obj.meter_id = reader.read('!L')[0]
+        obj.entries = meter_band.unpack_list(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.flags != other.flags: return False
+        if self.meter_id != other.meter_id: return False
+        if self.entries != other.entries: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("meter_config {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("meter_id = ");
+                q.text("%#x" % self.meter_id)
+                q.text(","); q.breakable()
+                q.text("entries = ");
+                q.pp(self.entries)
+            q.breakable()
+        q.text('}')
+
+class meter_features(object):
+
+    def __init__(self, max_meter=None, band_types=None, capabilities=None, max_bands=None, max_color=None):
+        if max_meter != None:
+            self.max_meter = max_meter
+        else:
+            self.max_meter = 0
+        if band_types != None:
+            self.band_types = band_types
+        else:
+            self.band_types = 0
+        if capabilities != None:
+            self.capabilities = capabilities
+        else:
+            self.capabilities = 0
+        if max_bands != None:
+            self.max_bands = max_bands
+        else:
+            self.max_bands = 0
+        if max_color != None:
+            self.max_color = max_color
+        else:
+            self.max_color = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.max_meter))
+        packed.append(struct.pack("!L", self.band_types))
+        packed.append(struct.pack("!L", self.capabilities))
+        packed.append(struct.pack("!B", self.max_bands))
+        packed.append(struct.pack("!B", self.max_color))
+        packed.append('\x00' * 2)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = meter_features()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.max_meter = reader.read('!L')[0]
+        obj.band_types = reader.read('!L')[0]
+        obj.capabilities = reader.read('!L')[0]
+        obj.max_bands = reader.read('!B')[0]
+        obj.max_color = reader.read('!B')[0]
+        reader.skip(2)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.max_meter != other.max_meter: return False
+        if self.band_types != other.band_types: return False
+        if self.capabilities != other.capabilities: return False
+        if self.max_bands != other.max_bands: return False
+        if self.max_color != other.max_color: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("meter_features {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("max_meter = ");
+                q.text("%#x" % self.max_meter)
+                q.text(","); q.breakable()
+                q.text("band_types = ");
+                q.text("%#x" % self.band_types)
+                q.text(","); q.breakable()
+                q.text("capabilities = ");
+                q.text("%#x" % self.capabilities)
+                q.text(","); q.breakable()
+                q.text("max_bands = ");
+                q.text("%#x" % self.max_bands)
+                q.text(","); q.breakable()
+                q.text("max_color = ");
+                q.text("%#x" % self.max_color)
+            q.breakable()
+        q.text('}')
+
+class meter_stats(object):
+
+    def __init__(self, meter_id=None, flow_count=None, packet_in_count=None, byte_in_count=None, duration_sec=None, duration_nsec=None, band_stats=None):
+        if meter_id != None:
+            self.meter_id = meter_id
+        else:
+            self.meter_id = 0
+        if flow_count != None:
+            self.flow_count = flow_count
+        else:
+            self.flow_count = 0
+        if packet_in_count != None:
+            self.packet_in_count = packet_in_count
+        else:
+            self.packet_in_count = 0
+        if byte_in_count != None:
+            self.byte_in_count = byte_in_count
+        else:
+            self.byte_in_count = 0
+        if duration_sec != None:
+            self.duration_sec = duration_sec
+        else:
+            self.duration_sec = 0
+        if duration_nsec != None:
+            self.duration_nsec = duration_nsec
+        else:
+            self.duration_nsec = 0
+        if band_stats != None:
+            self.band_stats = band_stats
+        else:
+            self.band_stats = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.meter_id))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 6)
+        packed.append(struct.pack("!L", self.flow_count))
+        packed.append(struct.pack("!Q", self.packet_in_count))
+        packed.append(struct.pack("!Q", self.byte_in_count))
+        packed.append(struct.pack("!L", self.duration_sec))
+        packed.append(struct.pack("!L", self.duration_nsec))
+        packed.append("".join([x.pack() for x in self.band_stats]))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = meter_stats()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.meter_id = reader.read('!L')[0]
+        _len = reader.read('!H')[0]
+        reader.skip(6)
+        obj.flow_count = reader.read('!L')[0]
+        obj.packet_in_count = reader.read('!Q')[0]
+        obj.byte_in_count = reader.read('!Q')[0]
+        obj.duration_sec = reader.read('!L')[0]
+        obj.duration_nsec = reader.read('!L')[0]
+        obj.band_stats = loxi.generic_util.unpack_list(reader, common.meter_band_stats.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.meter_id != other.meter_id: return False
+        if self.flow_count != other.flow_count: return False
+        if self.packet_in_count != other.packet_in_count: return False
+        if self.byte_in_count != other.byte_in_count: return False
+        if self.duration_sec != other.duration_sec: return False
+        if self.duration_nsec != other.duration_nsec: return False
+        if self.band_stats != other.band_stats: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("meter_stats {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("meter_id = ");
+                q.text("%#x" % self.meter_id)
+                q.text(","); q.breakable()
+                q.text("flow_count = ");
+                q.text("%#x" % self.flow_count)
+                q.text(","); q.breakable()
+                q.text("packet_in_count = ");
+                q.text("%#x" % self.packet_in_count)
+                q.text(","); q.breakable()
+                q.text("byte_in_count = ");
+                q.text("%#x" % self.byte_in_count)
+                q.text(","); q.breakable()
+                q.text("duration_sec = ");
+                q.text("%#x" % self.duration_sec)
+                q.text(","); q.breakable()
+                q.text("duration_nsec = ");
+                q.text("%#x" % self.duration_nsec)
+                q.text(","); q.breakable()
+                q.text("band_stats = ");
+                q.pp(self.band_stats)
+            q.breakable()
+        q.text('}')
+
+class packet_queue(object):
+
+    def __init__(self, queue_id=None, port=None, properties=None):
+        if queue_id != None:
+            self.queue_id = queue_id
+        else:
+            self.queue_id = 0
+        if port != None:
+            self.port = port
+        else:
+            self.port = 0
+        if properties != None:
+            self.properties = properties
+        else:
+            self.properties = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.queue_id))
+        packed.append(struct.pack("!L", self.port))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 2
+        packed.append('\x00' * 6)
+        packed.append("".join([x.pack() for x in self.properties]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = packet_queue()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.queue_id = reader.read('!L')[0]
+        obj.port = reader.read('!L')[0]
+        _len = reader.read('!H')[0]
+        reader.skip(6)
+        obj.properties = common.unpack_list_queue_prop(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.queue_id != other.queue_id: return False
+        if self.port != other.port: return False
+        if self.properties != other.properties: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("packet_queue {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("queue_id = ");
+                q.text("%#x" % self.queue_id)
+                q.text(","); q.breakable()
+                q.text("port = ");
+                q.text(util.pretty_port(self.port))
+                q.text(","); q.breakable()
+                q.text("properties = ");
+                q.pp(self.properties)
+            q.breakable()
+        q.text('}')
+
+class port_desc(object):
+
+    def __init__(self, port_no=None, hw_addr=None, name=None, config=None, state=None, curr=None, advertised=None, supported=None, peer=None, curr_speed=None, max_speed=None):
+        if port_no != None:
+            self.port_no = port_no
+        else:
+            self.port_no = 0
+        if hw_addr != None:
+            self.hw_addr = hw_addr
+        else:
+            self.hw_addr = [0,0,0,0,0,0]
+        if name != None:
+            self.name = name
+        else:
+            self.name = ""
+        if config != None:
+            self.config = config
+        else:
+            self.config = 0
+        if state != None:
+            self.state = state
+        else:
+            self.state = 0
+        if curr != None:
+            self.curr = curr
+        else:
+            self.curr = 0
+        if advertised != None:
+            self.advertised = advertised
+        else:
+            self.advertised = 0
+        if supported != None:
+            self.supported = supported
+        else:
+            self.supported = 0
+        if peer != None:
+            self.peer = peer
+        else:
+            self.peer = 0
+        if curr_speed != None:
+            self.curr_speed = curr_speed
+        else:
+            self.curr_speed = 0
+        if max_speed != None:
+            self.max_speed = max_speed
+        else:
+            self.max_speed = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.port_no))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!6B", *self.hw_addr))
+        packed.append('\x00' * 2)
+        packed.append(struct.pack("!16s", self.name))
+        packed.append(struct.pack("!L", self.config))
+        packed.append(struct.pack("!L", self.state))
+        packed.append(struct.pack("!L", self.curr))
+        packed.append(struct.pack("!L", self.advertised))
+        packed.append(struct.pack("!L", self.supported))
+        packed.append(struct.pack("!L", self.peer))
+        packed.append(struct.pack("!L", self.curr_speed))
+        packed.append(struct.pack("!L", self.max_speed))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = port_desc()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.port_no = reader.read('!L')[0]
+        reader.skip(4)
+        obj.hw_addr = list(reader.read('!6B'))
+        reader.skip(2)
+        obj.name = reader.read("!16s")[0].rstrip("\x00")
+        obj.config = reader.read('!L')[0]
+        obj.state = reader.read('!L')[0]
+        obj.curr = reader.read('!L')[0]
+        obj.advertised = reader.read('!L')[0]
+        obj.supported = reader.read('!L')[0]
+        obj.peer = reader.read('!L')[0]
+        obj.curr_speed = reader.read('!L')[0]
+        obj.max_speed = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.port_no != other.port_no: return False
+        if self.hw_addr != other.hw_addr: return False
+        if self.name != other.name: return False
+        if self.config != other.config: return False
+        if self.state != other.state: return False
+        if self.curr != other.curr: return False
+        if self.advertised != other.advertised: return False
+        if self.supported != other.supported: return False
+        if self.peer != other.peer: return False
+        if self.curr_speed != other.curr_speed: return False
+        if self.max_speed != other.max_speed: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("port_desc {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("port_no = ");
+                q.text(util.pretty_port(self.port_no))
+                q.text(","); q.breakable()
+                q.text("hw_addr = ");
+                q.text(util.pretty_mac(self.hw_addr))
+                q.text(","); q.breakable()
+                q.text("name = ");
+                q.pp(self.name)
+                q.text(","); q.breakable()
+                q.text("config = ");
+                q.text("%#x" % self.config)
+                q.text(","); q.breakable()
+                q.text("state = ");
+                q.text("%#x" % self.state)
+                q.text(","); q.breakable()
+                q.text("curr = ");
+                q.text("%#x" % self.curr)
+                q.text(","); q.breakable()
+                q.text("advertised = ");
+                q.text("%#x" % self.advertised)
+                q.text(","); q.breakable()
+                q.text("supported = ");
+                q.text("%#x" % self.supported)
+                q.text(","); q.breakable()
+                q.text("peer = ");
+                q.text("%#x" % self.peer)
+                q.text(","); q.breakable()
+                q.text("curr_speed = ");
+                q.text("%#x" % self.curr_speed)
+                q.text(","); q.breakable()
+                q.text("max_speed = ");
+                q.text("%#x" % self.max_speed)
+            q.breakable()
+        q.text('}')
+
+class port_stats_entry(object):
+
+    def __init__(self, port_no=None, rx_packets=None, tx_packets=None, rx_bytes=None, tx_bytes=None, rx_dropped=None, tx_dropped=None, rx_errors=None, tx_errors=None, rx_frame_err=None, rx_over_err=None, rx_crc_err=None, collisions=None, duration_sec=None, duration_nsec=None):
+        if port_no != None:
+            self.port_no = port_no
+        else:
+            self.port_no = 0
+        if rx_packets != None:
+            self.rx_packets = rx_packets
+        else:
+            self.rx_packets = 0
+        if tx_packets != None:
+            self.tx_packets = tx_packets
+        else:
+            self.tx_packets = 0
+        if rx_bytes != None:
+            self.rx_bytes = rx_bytes
+        else:
+            self.rx_bytes = 0
+        if tx_bytes != None:
+            self.tx_bytes = tx_bytes
+        else:
+            self.tx_bytes = 0
+        if rx_dropped != None:
+            self.rx_dropped = rx_dropped
+        else:
+            self.rx_dropped = 0
+        if tx_dropped != None:
+            self.tx_dropped = tx_dropped
+        else:
+            self.tx_dropped = 0
+        if rx_errors != None:
+            self.rx_errors = rx_errors
+        else:
+            self.rx_errors = 0
+        if tx_errors != None:
+            self.tx_errors = tx_errors
+        else:
+            self.tx_errors = 0
+        if rx_frame_err != None:
+            self.rx_frame_err = rx_frame_err
+        else:
+            self.rx_frame_err = 0
+        if rx_over_err != None:
+            self.rx_over_err = rx_over_err
+        else:
+            self.rx_over_err = 0
+        if rx_crc_err != None:
+            self.rx_crc_err = rx_crc_err
+        else:
+            self.rx_crc_err = 0
+        if collisions != None:
+            self.collisions = collisions
+        else:
+            self.collisions = 0
+        if duration_sec != None:
+            self.duration_sec = duration_sec
+        else:
+            self.duration_sec = 0
+        if duration_nsec != None:
+            self.duration_nsec = duration_nsec
+        else:
+            self.duration_nsec = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.port_no))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!Q", self.rx_packets))
+        packed.append(struct.pack("!Q", self.tx_packets))
+        packed.append(struct.pack("!Q", self.rx_bytes))
+        packed.append(struct.pack("!Q", self.tx_bytes))
+        packed.append(struct.pack("!Q", self.rx_dropped))
+        packed.append(struct.pack("!Q", self.tx_dropped))
+        packed.append(struct.pack("!Q", self.rx_errors))
+        packed.append(struct.pack("!Q", self.tx_errors))
+        packed.append(struct.pack("!Q", self.rx_frame_err))
+        packed.append(struct.pack("!Q", self.rx_over_err))
+        packed.append(struct.pack("!Q", self.rx_crc_err))
+        packed.append(struct.pack("!Q", self.collisions))
+        packed.append(struct.pack("!L", self.duration_sec))
+        packed.append(struct.pack("!L", self.duration_nsec))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = port_stats_entry()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.port_no = reader.read('!L')[0]
+        reader.skip(4)
+        obj.rx_packets = reader.read('!Q')[0]
+        obj.tx_packets = reader.read('!Q')[0]
+        obj.rx_bytes = reader.read('!Q')[0]
+        obj.tx_bytes = reader.read('!Q')[0]
+        obj.rx_dropped = reader.read('!Q')[0]
+        obj.tx_dropped = reader.read('!Q')[0]
+        obj.rx_errors = reader.read('!Q')[0]
+        obj.tx_errors = reader.read('!Q')[0]
+        obj.rx_frame_err = reader.read('!Q')[0]
+        obj.rx_over_err = reader.read('!Q')[0]
+        obj.rx_crc_err = reader.read('!Q')[0]
+        obj.collisions = reader.read('!Q')[0]
+        obj.duration_sec = reader.read('!L')[0]
+        obj.duration_nsec = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.port_no != other.port_no: return False
+        if self.rx_packets != other.rx_packets: return False
+        if self.tx_packets != other.tx_packets: return False
+        if self.rx_bytes != other.rx_bytes: return False
+        if self.tx_bytes != other.tx_bytes: return False
+        if self.rx_dropped != other.rx_dropped: return False
+        if self.tx_dropped != other.tx_dropped: return False
+        if self.rx_errors != other.rx_errors: return False
+        if self.tx_errors != other.tx_errors: return False
+        if self.rx_frame_err != other.rx_frame_err: return False
+        if self.rx_over_err != other.rx_over_err: return False
+        if self.rx_crc_err != other.rx_crc_err: return False
+        if self.collisions != other.collisions: return False
+        if self.duration_sec != other.duration_sec: return False
+        if self.duration_nsec != other.duration_nsec: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("port_stats_entry {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("port_no = ");
+                q.text(util.pretty_port(self.port_no))
+                q.text(","); q.breakable()
+                q.text("rx_packets = ");
+                q.text("%#x" % self.rx_packets)
+                q.text(","); q.breakable()
+                q.text("tx_packets = ");
+                q.text("%#x" % self.tx_packets)
+                q.text(","); q.breakable()
+                q.text("rx_bytes = ");
+                q.text("%#x" % self.rx_bytes)
+                q.text(","); q.breakable()
+                q.text("tx_bytes = ");
+                q.text("%#x" % self.tx_bytes)
+                q.text(","); q.breakable()
+                q.text("rx_dropped = ");
+                q.text("%#x" % self.rx_dropped)
+                q.text(","); q.breakable()
+                q.text("tx_dropped = ");
+                q.text("%#x" % self.tx_dropped)
+                q.text(","); q.breakable()
+                q.text("rx_errors = ");
+                q.text("%#x" % self.rx_errors)
+                q.text(","); q.breakable()
+                q.text("tx_errors = ");
+                q.text("%#x" % self.tx_errors)
+                q.text(","); q.breakable()
+                q.text("rx_frame_err = ");
+                q.text("%#x" % self.rx_frame_err)
+                q.text(","); q.breakable()
+                q.text("rx_over_err = ");
+                q.text("%#x" % self.rx_over_err)
+                q.text(","); q.breakable()
+                q.text("rx_crc_err = ");
+                q.text("%#x" % self.rx_crc_err)
+                q.text(","); q.breakable()
+                q.text("collisions = ");
+                q.text("%#x" % self.collisions)
+                q.text(","); q.breakable()
+                q.text("duration_sec = ");
+                q.text("%#x" % self.duration_sec)
+                q.text(","); q.breakable()
+                q.text("duration_nsec = ");
+                q.text("%#x" % self.duration_nsec)
+            q.breakable()
+        q.text('}')
+
+class queue_prop_experimenter(object):
+    type = const.OFPQT_EXPERIMENTER
+
+    def __init__(self, experimenter=None, data=None):
+        if experimenter != None:
+            self.experimenter = experimenter
+        else:
+            self.experimenter = 0
+        if data != None:
+            self.data = data
+        else:
+            self.data = ""
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append('\x00' * 4)
+        packed.append(self.data)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = queue_prop_experimenter()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPQT_EXPERIMENTER)
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        obj.experimenter = reader.read('!L')[0]
+        reader.skip(4)
+        obj.data = str(reader.read_all())
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.experimenter != other.experimenter: return False
+        if self.data != other.data: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("queue_prop_experimenter {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("experimenter = ");
+                q.text("%#x" % self.experimenter)
+                q.text(","); q.breakable()
+                q.text("data = ");
+                q.pp(self.data)
+            q.breakable()
+        q.text('}')
+
+class queue_prop_max_rate(object):
+    type = const.OFPQT_MAX_RATE
+
+    def __init__(self, rate=None):
+        if rate != None:
+            self.rate = rate
+        else:
+            self.rate = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!H", self.rate))
+        packed.append('\x00' * 6)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = queue_prop_max_rate()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPQT_MAX_RATE)
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        obj.rate = reader.read('!H')[0]
+        reader.skip(6)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.rate != other.rate: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("queue_prop_max_rate {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("rate = ");
+                q.text("%#x" % self.rate)
+            q.breakable()
+        q.text('}')
+
+class queue_prop_min_rate(object):
+    type = const.OFPQT_MIN_RATE
+
+    def __init__(self, rate=None):
+        if rate != None:
+            self.rate = rate
+        else:
+            self.rate = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for len at index 1
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!H", self.rate))
+        packed.append('\x00' * 6)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = queue_prop_min_rate()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type = reader.read('!H')[0]
+        assert(_type == const.OFPQT_MIN_RATE)
+        _len = reader.read('!H')[0]
+        reader.skip(4)
+        obj.rate = reader.read('!H')[0]
+        reader.skip(6)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.rate != other.rate: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("queue_prop_min_rate {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("rate = ");
+                q.text("%#x" % self.rate)
+            q.breakable()
+        q.text('}')
+
+class queue_stats_entry(object):
+
+    def __init__(self, port_no=None, queue_id=None, tx_bytes=None, tx_packets=None, tx_errors=None, duration_sec=None, duration_nsec=None):
+        if port_no != None:
+            self.port_no = port_no
+        else:
+            self.port_no = 0
+        if queue_id != None:
+            self.queue_id = queue_id
+        else:
+            self.queue_id = 0
+        if tx_bytes != None:
+            self.tx_bytes = tx_bytes
+        else:
+            self.tx_bytes = 0
+        if tx_packets != None:
+            self.tx_packets = tx_packets
+        else:
+            self.tx_packets = 0
+        if tx_errors != None:
+            self.tx_errors = tx_errors
+        else:
+            self.tx_errors = 0
+        if duration_sec != None:
+            self.duration_sec = duration_sec
+        else:
+            self.duration_sec = 0
+        if duration_nsec != None:
+            self.duration_nsec = duration_nsec
+        else:
+            self.duration_nsec = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.port_no))
+        packed.append(struct.pack("!L", self.queue_id))
+        packed.append(struct.pack("!Q", self.tx_bytes))
+        packed.append(struct.pack("!Q", self.tx_packets))
+        packed.append(struct.pack("!Q", self.tx_errors))
+        packed.append(struct.pack("!L", self.duration_sec))
+        packed.append(struct.pack("!L", self.duration_nsec))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = queue_stats_entry()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.port_no = reader.read('!L')[0]
+        obj.queue_id = reader.read('!L')[0]
+        obj.tx_bytes = reader.read('!Q')[0]
+        obj.tx_packets = reader.read('!Q')[0]
+        obj.tx_errors = reader.read('!Q')[0]
+        obj.duration_sec = reader.read('!L')[0]
+        obj.duration_nsec = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.port_no != other.port_no: return False
+        if self.queue_id != other.queue_id: return False
+        if self.tx_bytes != other.tx_bytes: return False
+        if self.tx_packets != other.tx_packets: return False
+        if self.tx_errors != other.tx_errors: return False
+        if self.duration_sec != other.duration_sec: return False
+        if self.duration_nsec != other.duration_nsec: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("queue_stats_entry {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("port_no = ");
+                q.text(util.pretty_port(self.port_no))
+                q.text(","); q.breakable()
+                q.text("queue_id = ");
+                q.text("%#x" % self.queue_id)
+                q.text(","); q.breakable()
+                q.text("tx_bytes = ");
+                q.text("%#x" % self.tx_bytes)
+                q.text(","); q.breakable()
+                q.text("tx_packets = ");
+                q.text("%#x" % self.tx_packets)
+                q.text(","); q.breakable()
+                q.text("tx_errors = ");
+                q.text("%#x" % self.tx_errors)
+                q.text(","); q.breakable()
+                q.text("duration_sec = ");
+                q.text("%#x" % self.duration_sec)
+                q.text(","); q.breakable()
+                q.text("duration_nsec = ");
+                q.text("%#x" % self.duration_nsec)
+            q.breakable()
+        q.text('}')
+
+class table_feature_prop_apply_actions(object):
+
+    def __init__(self, type=None, action_ids=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        if action_ids != None:
+            self.action_ids = action_ids
+        else:
+            self.action_ids = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 1
+        packed.append("".join([x.pack() for x in self.action_ids]))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = table_feature_prop_apply_actions()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _length = reader.read('!H')[0]
+        obj.action_ids = loxi.unimplemented('unpack list of_list_action_id_t')
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        if self.action_ids != other.action_ids: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_feature_prop_apply_actions {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+                q.text(","); q.breakable()
+                q.text("action_ids = ");
+                q.pp(self.action_ids)
+            q.breakable()
+        q.text('}')
+
+class table_feature_prop_apply_actions_miss(object):
+
+    def __init__(self, type=None, action_ids=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        if action_ids != None:
+            self.action_ids = action_ids
+        else:
+            self.action_ids = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 1
+        packed.append("".join([x.pack() for x in self.action_ids]))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = table_feature_prop_apply_actions_miss()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _length = reader.read('!H')[0]
+        obj.action_ids = loxi.unimplemented('unpack list of_list_action_id_t')
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        if self.action_ids != other.action_ids: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_feature_prop_apply_actions_miss {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+                q.text(","); q.breakable()
+                q.text("action_ids = ");
+                q.pp(self.action_ids)
+            q.breakable()
+        q.text('}')
+
+class table_feature_prop_apply_setfield(object):
+
+    def __init__(self, type=None, oxm_ids=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        if oxm_ids != None:
+            self.oxm_ids = oxm_ids
+        else:
+            self.oxm_ids = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 1
+        packed.append("".join([x.pack() for x in self.oxm_ids]))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = table_feature_prop_apply_setfield()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _length = reader.read('!H')[0]
+        obj.oxm_ids = loxi.generic_util.unpack_list(reader, common.uint32.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        if self.oxm_ids != other.oxm_ids: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_feature_prop_apply_setfield {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+                q.text(","); q.breakable()
+                q.text("oxm_ids = ");
+                q.pp(self.oxm_ids)
+            q.breakable()
+        q.text('}')
+
+class table_feature_prop_apply_setfield_miss(object):
+
+    def __init__(self, type=None, oxm_ids=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        if oxm_ids != None:
+            self.oxm_ids = oxm_ids
+        else:
+            self.oxm_ids = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 1
+        packed.append("".join([x.pack() for x in self.oxm_ids]))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = table_feature_prop_apply_setfield_miss()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _length = reader.read('!H')[0]
+        obj.oxm_ids = loxi.generic_util.unpack_list(reader, common.uint32.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        if self.oxm_ids != other.oxm_ids: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_feature_prop_apply_setfield_miss {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+                q.text(","); q.breakable()
+                q.text("oxm_ids = ");
+                q.pp(self.oxm_ids)
+            q.breakable()
+        q.text('}')
+
+class table_feature_prop_experimenter(object):
+
+    def __init__(self, type=None, experimenter=None, subtype=None, experimenter_data=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        if experimenter != None:
+            self.experimenter = experimenter
+        else:
+            self.experimenter = 0
+        if subtype != None:
+            self.subtype = subtype
+        else:
+            self.subtype = 0
+        if experimenter_data != None:
+            self.experimenter_data = experimenter_data
+        else:
+            self.experimenter_data = ""
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 1
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        packed.append(self.experimenter_data)
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = table_feature_prop_experimenter()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _length = reader.read('!H')[0]
+        obj.experimenter = reader.read('!L')[0]
+        obj.subtype = reader.read('!L')[0]
+        obj.experimenter_data = str(reader.read_all())
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        if self.experimenter != other.experimenter: return False
+        if self.subtype != other.subtype: return False
+        if self.experimenter_data != other.experimenter_data: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_feature_prop_experimenter {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+                q.text(","); q.breakable()
+                q.text("experimenter = ");
+                q.text("%#x" % self.experimenter)
+                q.text(","); q.breakable()
+                q.text("subtype = ");
+                q.text("%#x" % self.subtype)
+                q.text(","); q.breakable()
+                q.text("experimenter_data = ");
+                q.pp(self.experimenter_data)
+            q.breakable()
+        q.text('}')
+
+class table_feature_prop_instructions(object):
+
+    def __init__(self, type=None, instruction_ids=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        if instruction_ids != None:
+            self.instruction_ids = instruction_ids
+        else:
+            self.instruction_ids = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 1
+        packed.append("".join([x.pack() for x in self.instruction_ids]))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = table_feature_prop_instructions()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _length = reader.read('!H')[0]
+        obj.instruction_ids = instruction.unpack_list(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        if self.instruction_ids != other.instruction_ids: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_feature_prop_instructions {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+                q.text(","); q.breakable()
+                q.text("instruction_ids = ");
+                q.pp(self.instruction_ids)
+            q.breakable()
+        q.text('}')
+
+class table_feature_prop_instructions_miss(object):
+
+    def __init__(self, type=None, instruction_ids=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        if instruction_ids != None:
+            self.instruction_ids = instruction_ids
+        else:
+            self.instruction_ids = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 1
+        packed.append("".join([x.pack() for x in self.instruction_ids]))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = table_feature_prop_instructions_miss()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _length = reader.read('!H')[0]
+        obj.instruction_ids = instruction.unpack_list(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        if self.instruction_ids != other.instruction_ids: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_feature_prop_instructions_miss {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+                q.text(","); q.breakable()
+                q.text("instruction_ids = ");
+                q.pp(self.instruction_ids)
+            q.breakable()
+        q.text('}')
+
+class table_feature_prop_match(object):
+
+    def __init__(self, type=None, oxm_ids=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        if oxm_ids != None:
+            self.oxm_ids = oxm_ids
+        else:
+            self.oxm_ids = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 1
+        packed.append("".join([x.pack() for x in self.oxm_ids]))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = table_feature_prop_match()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _length = reader.read('!H')[0]
+        obj.oxm_ids = loxi.generic_util.unpack_list(reader, common.uint32.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        if self.oxm_ids != other.oxm_ids: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_feature_prop_match {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+                q.text(","); q.breakable()
+                q.text("oxm_ids = ");
+                q.pp(self.oxm_ids)
+            q.breakable()
+        q.text('}')
+
+class table_feature_prop_next_tables(object):
+
+    def __init__(self, type=None, next_table_ids=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        if next_table_ids != None:
+            self.next_table_ids = next_table_ids
+        else:
+            self.next_table_ids = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 1
+        packed.append("".join([x.pack() for x in self.next_table_ids]))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = table_feature_prop_next_tables()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _length = reader.read('!H')[0]
+        obj.next_table_ids = loxi.generic_util.unpack_list(reader, common.uint8.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        if self.next_table_ids != other.next_table_ids: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_feature_prop_next_tables {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+                q.text(","); q.breakable()
+                q.text("next_table_ids = ");
+                q.pp(self.next_table_ids)
+            q.breakable()
+        q.text('}')
+
+class table_feature_prop_next_tables_miss(object):
+
+    def __init__(self, type=None, next_table_ids=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        if next_table_ids != None:
+            self.next_table_ids = next_table_ids
+        else:
+            self.next_table_ids = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 1
+        packed.append("".join([x.pack() for x in self.next_table_ids]))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = table_feature_prop_next_tables_miss()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _length = reader.read('!H')[0]
+        obj.next_table_ids = loxi.generic_util.unpack_list(reader, common.uint8.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        if self.next_table_ids != other.next_table_ids: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_feature_prop_next_tables_miss {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+                q.text(","); q.breakable()
+                q.text("next_table_ids = ");
+                q.pp(self.next_table_ids)
+            q.breakable()
+        q.text('}')
+
+class table_feature_prop_wildcards(object):
+
+    def __init__(self, type=None, oxm_ids=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        if oxm_ids != None:
+            self.oxm_ids = oxm_ids
+        else:
+            self.oxm_ids = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 1
+        packed.append("".join([x.pack() for x in self.oxm_ids]))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = table_feature_prop_wildcards()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _length = reader.read('!H')[0]
+        obj.oxm_ids = loxi.generic_util.unpack_list(reader, common.uint32.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        if self.oxm_ids != other.oxm_ids: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_feature_prop_wildcards {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+                q.text(","); q.breakable()
+                q.text("oxm_ids = ");
+                q.pp(self.oxm_ids)
+            q.breakable()
+        q.text('}')
+
+class table_feature_prop_write_actions(object):
+
+    def __init__(self, type=None, action_ids=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        if action_ids != None:
+            self.action_ids = action_ids
+        else:
+            self.action_ids = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 1
+        packed.append("".join([x.pack() for x in self.action_ids]))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = table_feature_prop_write_actions()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _length = reader.read('!H')[0]
+        obj.action_ids = loxi.unimplemented('unpack list of_list_action_id_t')
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        if self.action_ids != other.action_ids: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_feature_prop_write_actions {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+                q.text(","); q.breakable()
+                q.text("action_ids = ");
+                q.pp(self.action_ids)
+            q.breakable()
+        q.text('}')
+
+class table_feature_prop_write_actions_miss(object):
+
+    def __init__(self, type=None, action_ids=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        if action_ids != None:
+            self.action_ids = action_ids
+        else:
+            self.action_ids = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 1
+        packed.append("".join([x.pack() for x in self.action_ids]))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = table_feature_prop_write_actions_miss()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _length = reader.read('!H')[0]
+        obj.action_ids = loxi.unimplemented('unpack list of_list_action_id_t')
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        if self.action_ids != other.action_ids: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_feature_prop_write_actions_miss {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+                q.text(","); q.breakable()
+                q.text("action_ids = ");
+                q.pp(self.action_ids)
+            q.breakable()
+        q.text('}')
+
+class table_feature_prop_write_setfield(object):
+
+    def __init__(self, type=None, oxm_ids=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        if oxm_ids != None:
+            self.oxm_ids = oxm_ids
+        else:
+            self.oxm_ids = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 1
+        packed.append("".join([x.pack() for x in self.oxm_ids]))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = table_feature_prop_write_setfield()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _length = reader.read('!H')[0]
+        obj.oxm_ids = loxi.generic_util.unpack_list(reader, common.uint32.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        if self.oxm_ids != other.oxm_ids: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_feature_prop_write_setfield {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+                q.text(","); q.breakable()
+                q.text("oxm_ids = ");
+                q.pp(self.oxm_ids)
+            q.breakable()
+        q.text('}')
+
+class table_feature_prop_write_setfield_miss(object):
+
+    def __init__(self, type=None, oxm_ids=None):
+        if type != None:
+            self.type = type
+        else:
+            self.type = 0
+        if oxm_ids != None:
+            self.oxm_ids = oxm_ids
+        else:
+            self.oxm_ids = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 1
+        packed.append("".join([x.pack() for x in self.oxm_ids]))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = table_feature_prop_write_setfield_miss()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.type = reader.read('!H')[0]
+        _length = reader.read('!H')[0]
+        obj.oxm_ids = loxi.generic_util.unpack_list(reader, common.uint32.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.type != other.type: return False
+        if self.oxm_ids != other.oxm_ids: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_feature_prop_write_setfield_miss {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("type = ");
+                q.text("%#x" % self.type)
+                q.text(","); q.breakable()
+                q.text("oxm_ids = ");
+                q.pp(self.oxm_ids)
+            q.breakable()
+        q.text('}')
+
+class table_features(object):
+
+    def __init__(self, table_id=None, name=None, metadata_match=None, metadata_write=None, config=None, max_entries=None, properties=None):
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if name != None:
+            self.name = name
+        else:
+            self.name = ""
+        if metadata_match != None:
+            self.metadata_match = metadata_match
+        else:
+            self.metadata_match = 0
+        if metadata_write != None:
+            self.metadata_write = metadata_write
+        else:
+            self.metadata_write = 0
+        if config != None:
+            self.config = config
+        else:
+            self.config = 0
+        if max_entries != None:
+            self.max_entries = max_entries
+        else:
+            self.max_entries = 0
+        if properties != None:
+            self.properties = properties
+        else:
+            self.properties = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 0
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append('\x00' * 5)
+        packed.append(struct.pack("!32s", self.name))
+        packed.append(struct.pack("!Q", self.metadata_match))
+        packed.append(struct.pack("!Q", self.metadata_write))
+        packed.append(struct.pack("!L", self.config))
+        packed.append(struct.pack("!L", self.max_entries))
+        packed.append("".join([x.pack() for x in self.properties]))
+        length = sum([len(x) for x in packed])
+        packed[0] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = table_features()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _length = reader.read('!H')[0]
+        obj.table_id = reader.read('!B')[0]
+        reader.skip(5)
+        obj.name = reader.read("!32s")[0].rstrip("\x00")
+        obj.metadata_match = reader.read('!Q')[0]
+        obj.metadata_write = reader.read('!Q')[0]
+        obj.config = reader.read('!L')[0]
+        obj.max_entries = reader.read('!L')[0]
+        obj.properties = loxi.unimplemented('unpack list of_list_table_feature_prop_t')
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.table_id != other.table_id: return False
+        if self.name != other.name: return False
+        if self.metadata_match != other.metadata_match: return False
+        if self.metadata_write != other.metadata_write: return False
+        if self.config != other.config: return False
+        if self.max_entries != other.max_entries: return False
+        if self.properties != other.properties: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_features {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("name = ");
+                q.pp(self.name)
+                q.text(","); q.breakable()
+                q.text("metadata_match = ");
+                q.text("%#x" % self.metadata_match)
+                q.text(","); q.breakable()
+                q.text("metadata_write = ");
+                q.text("%#x" % self.metadata_write)
+                q.text(","); q.breakable()
+                q.text("config = ");
+                q.text("%#x" % self.config)
+                q.text(","); q.breakable()
+                q.text("max_entries = ");
+                q.text("%#x" % self.max_entries)
+                q.text(","); q.breakable()
+                q.text("properties = ");
+                q.pp(self.properties)
+            q.breakable()
+        q.text('}')
+
+class table_stats_entry(object):
+
+    def __init__(self, table_id=None, active_count=None, lookup_count=None, matched_count=None):
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if active_count != None:
+            self.active_count = active_count
+        else:
+            self.active_count = 0
+        if lookup_count != None:
+            self.lookup_count = lookup_count
+        else:
+            self.lookup_count = 0
+        if matched_count != None:
+            self.matched_count = matched_count
+        else:
+            self.matched_count = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append('\x00' * 3)
+        packed.append(struct.pack("!L", self.active_count))
+        packed.append(struct.pack("!Q", self.lookup_count))
+        packed.append(struct.pack("!Q", self.matched_count))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = table_stats_entry()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.table_id = reader.read('!B')[0]
+        reader.skip(3)
+        obj.active_count = reader.read('!L')[0]
+        obj.lookup_count = reader.read('!Q')[0]
+        obj.matched_count = reader.read('!Q')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.table_id != other.table_id: return False
+        if self.active_count != other.active_count: return False
+        if self.lookup_count != other.lookup_count: return False
+        if self.matched_count != other.matched_count: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_stats_entry {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("active_count = ");
+                q.text("%#x" % self.active_count)
+                q.text(","); q.breakable()
+                q.text("lookup_count = ");
+                q.text("%#x" % self.lookup_count)
+                q.text(","); q.breakable()
+                q.text("matched_count = ");
+                q.text("%#x" % self.matched_count)
+            q.breakable()
+        q.text('}')
+
+class uint32(object):
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = uint32()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.value = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("uint32 {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class uint8(object):
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = uint8()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        obj.value = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("uint8 {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+
+match = match_v3
diff --git a/src/python/loxi/of13/const.py b/src/python/loxi/of13/const.py
new file mode 100644
index 0000000..c04b1db
--- /dev/null
+++ b/src/python/loxi/of13/const.py
@@ -0,0 +1,954 @@
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+
+# Automatically generated by LOXI from template const.py
+# Do not modify
+
+OFP_VERSION = 4
+
+# Identifiers from group macro_definitions
+OFP_VLAN_NONE = 0
+OFP_FLOW_PERMANENT = 0
+OFP_ETH_ALEN = 6
+OFP_MAX_PORT_NAME_LEN = 16
+OFP_MAX_TABLE_NAME_LEN = 32
+SERIAL_NUM_LEN = 32
+OFP_DEFAULT_MISS_SEND_LEN = 128
+DESC_STR_LEN = 256
+OFP_TCP_PORT = 6633
+OFP_SSL_PORT = 6633
+OFP_DEFAULT_PRIORITY = 32768
+OFPQ_MIN_RATE_UNCFG = 65535
+OFPQ_MAX_RATE_UNCFG = 65535
+OFPQ_ALL = 4294967295
+OFP_NO_BUFFER = 4294967295
+
+# Identifiers from group ofp_action_type
+OFPAT_OUTPUT = 0
+OFPAT_COPY_TTL_OUT = 11
+OFPAT_COPY_TTL_IN = 12
+OFPAT_SET_MPLS_TTL = 15
+OFPAT_DEC_MPLS_TTL = 16
+OFPAT_PUSH_VLAN = 17
+OFPAT_POP_VLAN = 18
+OFPAT_PUSH_MPLS = 19
+OFPAT_POP_MPLS = 20
+OFPAT_SET_QUEUE = 21
+OFPAT_GROUP = 22
+OFPAT_SET_NW_TTL = 23
+OFPAT_DEC_NW_TTL = 24
+OFPAT_SET_FIELD = 25
+OFPAT_PUSH_PBB = 26
+OFPAT_POP_PBB = 27
+OFPAT_EXPERIMENTER = 65535
+
+ofp_action_type_map = {
+    0: 'OFPAT_OUTPUT',
+    11: 'OFPAT_COPY_TTL_OUT',
+    12: 'OFPAT_COPY_TTL_IN',
+    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',
+}
+
+# Identifiers from group ofp_bad_action_code
+OFPBAC_BAD_TYPE = 0
+OFPBAC_BAD_LEN = 1
+OFPBAC_BAD_EXPERIMENTER = 2
+OFPBAC_BAD_EXP_TYPE = 3
+OFPBAC_BAD_OUT_PORT = 4
+OFPBAC_BAD_ARGUMENT = 5
+OFPBAC_EPERM = 6
+OFPBAC_TOO_MANY = 7
+OFPBAC_BAD_QUEUE = 8
+OFPBAC_BAD_OUT_GROUP = 9
+OFPBAC_MATCH_INCONSISTENT = 10
+OFPBAC_UNSUPPORTED_ORDER = 11
+OFPBAC_BAD_TAG = 12
+OFPBAC_BAD_SET_TYPE = 13
+OFPBAC_BAD_SET_LEN = 14
+OFPBAC_BAD_SET_ARGUMENT = 15
+
+ofp_bad_action_code_map = {
+    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',
+}
+
+# Identifiers from group ofp_bad_instruction_code
+OFPBIC_UNKNOWN_INST = 0
+OFPBIC_UNSUP_INST = 1
+OFPBIC_BAD_TABLE_ID = 2
+OFPBIC_UNSUP_METADATA = 3
+OFPBIC_UNSUP_METADATA_MASK = 4
+OFPBIC_BAD_EXPERIMENTER = 5
+OFPBIC_BAD_EXP_TYPE = 6
+OFPBIC_BAD_LEN = 7
+OFPBIC_EPERM = 8
+
+ofp_bad_instruction_code_map = {
+    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',
+}
+
+# Identifiers from group ofp_bad_match_code
+OFPBMC_BAD_TYPE = 0
+OFPBMC_BAD_LEN = 1
+OFPBMC_BAD_TAG = 2
+OFPBMC_BAD_DL_ADDR_MASK = 3
+OFPBMC_BAD_NW_ADDR_MASK = 4
+OFPBMC_BAD_WILDCARDS = 5
+OFPBMC_BAD_FIELD = 6
+OFPBMC_BAD_VALUE = 7
+OFPBMC_BAD_MASK = 8
+OFPBMC_BAD_PREREQ = 9
+OFPBMC_DUP_FIELD = 10
+OFPBMC_EPERM = 11
+
+ofp_bad_match_code_map = {
+    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',
+}
+
+# Identifiers from group ofp_bad_request_code
+OFPBRC_BAD_VERSION = 0
+OFPBRC_BAD_TYPE = 1
+OFPBRC_BAD_MULTIPART = 2
+OFPBRC_BAD_EXPERIMENTER = 3
+OFPBRC_BAD_EXP_TYPE = 4
+OFPBRC_EPERM = 5
+OFPBRC_BAD_LEN = 6
+OFPBRC_BUFFER_EMPTY = 7
+OFPBRC_BUFFER_UNKNOWN = 8
+OFPBRC_BAD_TABLE_ID = 9
+OFPBRC_IS_SLAVE = 10
+OFPBRC_BAD_PORT = 11
+OFPBRC_BAD_PACKET = 12
+OFPBRC_MULTIPART_BUFFER_OVERFLOW = 13
+
+ofp_bad_request_code_map = {
+    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',
+}
+
+# Identifiers from group ofp_capabilities
+OFPC_FLOW_STATS = 1
+OFPC_TABLE_STATS = 2
+OFPC_PORT_STATS = 4
+OFPC_GROUP_STATS = 8
+OFPC_IP_REASM = 32
+OFPC_QUEUE_STATS = 64
+OFPC_PORT_BLOCKED = 256
+
+ofp_capabilities_map = {
+    1: 'OFPC_FLOW_STATS',
+    2: 'OFPC_TABLE_STATS',
+    4: 'OFPC_PORT_STATS',
+    8: 'OFPC_GROUP_STATS',
+    32: 'OFPC_IP_REASM',
+    64: 'OFPC_QUEUE_STATS',
+    256: 'OFPC_PORT_BLOCKED',
+}
+
+# Identifiers from group ofp_config_flags
+OFPC_FRAG_NORMAL = 0
+OFPC_FRAG_DROP = 1
+OFPC_FRAG_REASM = 2
+OFPC_FRAG_MASK = 3
+
+ofp_config_flags_map = {
+    0: 'OFPC_FRAG_NORMAL',
+    1: 'OFPC_FRAG_DROP',
+    2: 'OFPC_FRAG_REASM',
+    3: 'OFPC_FRAG_MASK',
+}
+
+# Identifiers from group ofp_controller_max_len
+OFPCML_MAX = 65509
+OFPCML_NO_BUFFER = 65535
+
+ofp_controller_max_len_map = {
+    65509: 'OFPCML_MAX',
+    65535: 'OFPCML_NO_BUFFER',
+}
+
+# Identifiers from group ofp_controller_role
+OFPCR_ROLE_NOCHANGE = 0
+OFPCR_ROLE_EQUAL = 1
+OFPCR_ROLE_MASTER = 2
+OFPCR_ROLE_SLAVE = 3
+
+ofp_controller_role_map = {
+    0: 'OFPCR_ROLE_NOCHANGE',
+    1: 'OFPCR_ROLE_EQUAL',
+    2: 'OFPCR_ROLE_MASTER',
+    3: 'OFPCR_ROLE_SLAVE',
+}
+
+# Identifiers from group ofp_error_type
+OFPET_HELLO_FAILED = 0
+OFPET_BAD_REQUEST = 1
+OFPET_BAD_ACTION = 2
+OFPET_BAD_INSTRUCTION = 3
+OFPET_BAD_MATCH = 4
+OFPET_FLOW_MOD_FAILED = 5
+OFPET_GROUP_MOD_FAILED = 6
+OFPET_PORT_MOD_FAILED = 7
+OFPET_TABLE_MOD_FAILED = 8
+OFPET_QUEUE_OP_FAILED = 9
+OFPET_SWITCH_CONFIG_FAILED = 10
+OFPET_ROLE_REQUEST_FAILED = 11
+OFPET_METER_MOD_FAILED = 12
+OFPET_TABLE_FEATURES_FAILED = 13
+OFPET_EXPERIMENTER = 65535
+
+ofp_error_type_map = {
+    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',
+}
+
+# Identifiers from group ofp_flow_mod_command
+OFPFC_ADD = 0
+OFPFC_MODIFY = 1
+OFPFC_MODIFY_STRICT = 2
+OFPFC_DELETE = 3
+OFPFC_DELETE_STRICT = 4
+
+ofp_flow_mod_command_map = {
+    0: 'OFPFC_ADD',
+    1: 'OFPFC_MODIFY',
+    2: 'OFPFC_MODIFY_STRICT',
+    3: 'OFPFC_DELETE',
+    4: 'OFPFC_DELETE_STRICT',
+}
+
+# Identifiers from group ofp_flow_mod_failed_code
+OFPFMFC_UNKNOWN = 0
+OFPFMFC_TABLE_FULL = 1
+OFPFMFC_BAD_TABLE_ID = 2
+OFPFMFC_OVERLAP = 3
+OFPFMFC_EPERM = 4
+OFPFMFC_BAD_TIMEOUT = 5
+OFPFMFC_BAD_COMMAND = 6
+OFPFMFC_BAD_FLAGS = 7
+
+ofp_flow_mod_failed_code_map = {
+    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',
+}
+
+# Identifiers from group ofp_flow_mod_flags
+OFPFF_SEND_FLOW_REM = 1
+OFPFF_CHECK_OVERLAP = 2
+OFPFF_RESET_COUNTS = 4
+OFPFF_NO_PKT_COUNTS = 8
+OFPFF_NO_BYT_COUNTS = 16
+
+ofp_flow_mod_flags_map = {
+    1: 'OFPFF_SEND_FLOW_REM',
+    2: 'OFPFF_CHECK_OVERLAP',
+    4: 'OFPFF_RESET_COUNTS',
+    8: 'OFPFF_NO_PKT_COUNTS',
+    16: 'OFPFF_NO_BYT_COUNTS',
+}
+
+# Identifiers from group ofp_flow_removed_reason
+OFPRR_IDLE_TIMEOUT = 0
+OFPRR_HARD_TIMEOUT = 1
+OFPRR_DELETE = 2
+OFPRR_GROUP_DELETE = 3
+
+ofp_flow_removed_reason_map = {
+    0: 'OFPRR_IDLE_TIMEOUT',
+    1: 'OFPRR_HARD_TIMEOUT',
+    2: 'OFPRR_DELETE',
+    3: 'OFPRR_GROUP_DELETE',
+}
+
+# Identifiers from group ofp_group
+OFPG_MAX = 4294967040
+OFPG_ALL = 4294967292
+OFPG_ANY = 4294967295
+
+ofp_group_map = {
+    4294967040: 'OFPG_MAX',
+    4294967292: 'OFPG_ALL',
+    4294967295: 'OFPG_ANY',
+}
+
+# Identifiers from group ofp_group_capabilities
+OFPGFC_SELECT_WEIGHT = 1
+OFPGFC_SELECT_LIVENESS = 2
+OFPGFC_CHAINING = 4
+OFPGFC_CHAINING_CHECKS = 8
+
+ofp_group_capabilities_map = {
+    1: 'OFPGFC_SELECT_WEIGHT',
+    2: 'OFPGFC_SELECT_LIVENESS',
+    4: 'OFPGFC_CHAINING',
+    8: 'OFPGFC_CHAINING_CHECKS',
+}
+
+# Identifiers from group ofp_group_mod_command
+OFPGC_ADD = 0
+OFPGC_MODIFY = 1
+OFPGC_DELETE = 2
+
+ofp_group_mod_command_map = {
+    0: 'OFPGC_ADD',
+    1: 'OFPGC_MODIFY',
+    2: 'OFPGC_DELETE',
+}
+
+# Identifiers from group ofp_group_mod_failed_code
+OFPGMFC_GROUP_EXISTS = 0
+OFPGMFC_INVALID_GROUP = 1
+OFPGMFC_WEIGHT_UNSUPPORTED = 2
+OFPGMFC_OUT_OF_GROUPS = 3
+OFPGMFC_OUT_OF_BUCKETS = 4
+OFPGMFC_CHAINING_UNSUPPORTED = 5
+OFPGMFC_WATCH_UNSUPPORTED = 6
+OFPGMFC_LOOP = 7
+OFPGMFC_UNKNOWN_GROUP = 8
+OFPGMFC_CHAINED_GROUP = 9
+OFPGMFC_BAD_TYPE = 10
+OFPGMFC_BAD_COMMAND = 11
+OFPGMFC_BAD_BUCKET = 12
+OFPGMFC_BAD_WATCH = 13
+OFPGMFC_EPERM = 14
+
+ofp_group_mod_failed_code_map = {
+    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: 'OFPGMFC_EPERM',
+}
+
+# Identifiers from group ofp_group_type
+OFPGT_ALL = 0
+OFPGT_SELECT = 1
+OFPGT_INDIRECT = 2
+OFPGT_FF = 3
+
+ofp_group_type_map = {
+    0: 'OFPGT_ALL',
+    1: 'OFPGT_SELECT',
+    2: 'OFPGT_INDIRECT',
+    3: 'OFPGT_FF',
+}
+
+# Identifiers from group ofp_hello_elem_type
+OFPHET_VERSIONBITMAP = 1
+
+ofp_hello_elem_type_map = {
+    1: 'OFPHET_VERSIONBITMAP',
+}
+
+# Identifiers from group ofp_hello_failed_code
+OFPHFC_INCOMPATIBLE = 0
+OFPHFC_EPERM = 1
+
+ofp_hello_failed_code_map = {
+    0: 'OFPHFC_INCOMPATIBLE',
+    1: 'OFPHFC_EPERM',
+}
+
+# Identifiers from group ofp_instruction_type
+OFPIT_GOTO_TABLE = 1
+OFPIT_WRITE_METADATA = 2
+OFPIT_WRITE_ACTIONS = 3
+OFPIT_APPLY_ACTIONS = 4
+OFPIT_CLEAR_ACTIONS = 5
+OFPIT_METER = 6
+OFPIT_EXPERIMENTER = 65535
+
+ofp_instruction_type_map = {
+    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',
+}
+
+# Identifiers from group ofp_ipv6exthdr_flags
+OFPIEH_NONEXT = 1
+OFPIEH_ESP = 2
+OFPIEH_AUTH = 4
+OFPIEH_DEST = 8
+OFPIEH_FRAG = 16
+OFPIEH_ROUTER = 32
+OFPIEH_HOP = 64
+OFPIEH_UNREP = 128
+OFPIEH_UNSEQ = 256
+
+ofp_ipv6exthdr_flags_map = {
+    1: 'OFPIEH_NONEXT',
+    2: 'OFPIEH_ESP',
+    4: 'OFPIEH_AUTH',
+    8: 'OFPIEH_DEST',
+    16: 'OFPIEH_FRAG',
+    32: 'OFPIEH_ROUTER',
+    64: 'OFPIEH_HOP',
+    128: 'OFPIEH_UNREP',
+    256: 'OFPIEH_UNSEQ',
+}
+
+# Identifiers from group ofp_match_type
+OFPMT_STANDARD = 0
+OFPMT_OXM = 1
+
+ofp_match_type_map = {
+    0: 'OFPMT_STANDARD',
+    1: 'OFPMT_OXM',
+}
+
+# Identifiers from group ofp_meter
+OFPM_MAX = 4294901760
+OFPM_SLOWPATH = 4294967293
+OFPM_CONTROLLER = 4294967294
+OFPM_ALL = 4294967295
+
+ofp_meter_map = {
+    4294901760: 'OFPM_MAX',
+    4294967293: 'OFPM_SLOWPATH',
+    4294967294: 'OFPM_CONTROLLER',
+    4294967295: 'OFPM_ALL',
+}
+
+# Identifiers from group ofp_meter_band_type
+OFPMBT_DROP = 1
+OFPMBT_DSCP_REMARK = 2
+OFPMBT_EXPERIMENTER = 65535
+
+ofp_meter_band_type_map = {
+    1: 'OFPMBT_DROP',
+    2: 'OFPMBT_DSCP_REMARK',
+    65535: 'OFPMBT_EXPERIMENTER',
+}
+
+# Identifiers from group ofp_meter_flags
+OFPMF_KBPS = 1
+OFPMF_PKTPS = 2
+OFPMF_BURST = 4
+OFPMF_STATS = 8
+
+ofp_meter_flags_map = {
+    1: 'OFPMF_KBPS',
+    2: 'OFPMF_PKTPS',
+    4: 'OFPMF_BURST',
+    8: 'OFPMF_STATS',
+}
+
+# Identifiers from group ofp_meter_mod_command
+OFPMC_ADD = 0
+OFPMC_MODIFY = 1
+OFPMC_DELETE = 2
+
+ofp_meter_mod_command_map = {
+    0: 'OFPMC_ADD',
+    1: 'OFPMC_MODIFY',
+    2: 'OFPMC_DELETE',
+}
+
+# Identifiers from group ofp_meter_mod_failed_code
+OFPMMFC_UNKNOWN = 0
+OFPMMFC_METER_EXISTS = 1
+OFPMMFC_INVALID_METER = 2
+OFPMMFC_UNKNOWN_METER = 3
+OFPMMFC_BAD_COMMAND = 4
+OFPMMFC_BAD_FLAGS = 5
+OFPMMFC_BAD_RATE = 6
+OFPMMFC_BAD_BURST = 7
+OFPMMFC_BAD_BAND = 8
+OFPMMFC_BAD_BAND_VALUE = 9
+OFPMMFC_OUT_OF_METERS = 10
+OFPMMFC_OUT_OF_BANDS = 11
+
+ofp_meter_mod_failed_code_map = {
+    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',
+}
+
+# Identifiers from group ofp_multipart_reply_flags
+OFPMPF_REPLY_MORE = 1
+
+ofp_multipart_reply_flags_map = {
+    1: 'OFPMPF_REPLY_MORE',
+}
+
+# Identifiers from group ofp_multipart_request_flags
+OFPMPF_REQ_MORE = 1
+
+ofp_multipart_request_flags_map = {
+    1: 'OFPMPF_REQ_MORE',
+}
+
+# Identifiers from group ofp_multipart_types
+OFPMP_DESC = 0
+OFPMP_FLOW = 1
+OFPMP_AGGREGATE = 2
+OFPMP_TABLE = 3
+OFPMP_PORT_STATS = 4
+OFPMP_QUEUE = 5
+OFPMP_GROUP = 6
+OFPMP_GROUP_DESC = 7
+OFPMP_GROUP_FEATURES = 8
+OFPMP_METER = 9
+OFPMP_METER_CONFIG = 10
+OFPMP_METER_FEATURES = 11
+OFPMP_TABLE_FEATURES = 12
+OFPMP_PORT_DESC = 13
+OFPMP_EXPERIMENTER = 65535
+
+ofp_multipart_types_map = {
+    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: 'OFPMP_EXPERIMENTER',
+}
+
+# Identifiers from group ofp_oxm_class
+OFPXMC_NXM_0 = 0
+OFPXMC_NXM_1 = 1
+OFPXMC_OPENFLOW_BASIC = 32768
+OFPXMC_EXPERIMENTER = 65535
+
+ofp_oxm_class_map = {
+    0: 'OFPXMC_NXM_0',
+    1: 'OFPXMC_NXM_1',
+    32768: 'OFPXMC_OPENFLOW_BASIC',
+    65535: 'OFPXMC_EXPERIMENTER',
+}
+
+# Identifiers from group ofp_packet_in_reason
+OFPR_NO_MATCH = 0
+OFPR_ACTION = 1
+OFPR_INVALID_TTL = 2
+
+ofp_packet_in_reason_map = {
+    0: 'OFPR_NO_MATCH',
+    1: 'OFPR_ACTION',
+    2: 'OFPR_INVALID_TTL',
+}
+
+# Identifiers from group ofp_port
+OFPP_MAX = 4294967040
+OFPP_IN_PORT = 4294967288
+OFPP_TABLE = 4294967289
+OFPP_NORMAL = 4294967290
+OFPP_FLOOD = 4294967291
+OFPP_ALL = 4294967292
+OFPP_CONTROLLER = 4294967293
+OFPP_LOCAL = 4294967294
+
+ofp_port_map = {
+    4294967040: 'OFPP_MAX',
+    4294967288: 'OFPP_IN_PORT',
+    4294967289: 'OFPP_TABLE',
+    4294967290: 'OFPP_NORMAL',
+    4294967291: 'OFPP_FLOOD',
+    4294967292: 'OFPP_ALL',
+    4294967293: 'OFPP_CONTROLLER',
+    4294967294: 'OFPP_LOCAL',
+}
+
+# Identifiers from group ofp_port_config
+OFPPC_PORT_DOWN = 1
+OFPPC_NO_RECV = 4
+OFPPC_NO_FWD = 32
+OFPPC_NO_PACKET_IN = 64
+
+ofp_port_config_map = {
+    1: 'OFPPC_PORT_DOWN',
+    4: 'OFPPC_NO_RECV',
+    32: 'OFPPC_NO_FWD',
+    64: 'OFPPC_NO_PACKET_IN',
+}
+
+# Identifiers from group ofp_port_features
+OFPPF_10MB_HD = 1
+OFPPF_10MB_FD = 2
+OFPPF_100MB_HD = 4
+OFPPF_100MB_FD = 8
+OFPPF_1GB_HD = 16
+OFPPF_1GB_FD = 32
+OFPPF_10GB_FD = 64
+OFPPF_40GB_FD = 128
+OFPPF_100GB_FD = 256
+OFPPF_1TB_FD = 512
+OFPPF_OTHER = 1024
+OFPPF_COPPER = 2048
+OFPPF_FIBER = 4096
+OFPPF_AUTONEG = 8192
+OFPPF_PAUSE = 16384
+OFPPF_PAUSE_ASYM = 32768
+
+ofp_port_features_map = {
+    1: 'OFPPF_10MB_HD',
+    2: 'OFPPF_10MB_FD',
+    4: 'OFPPF_100MB_HD',
+    8: 'OFPPF_100MB_FD',
+    16: 'OFPPF_1GB_HD',
+    32: 'OFPPF_1GB_FD',
+    64: 'OFPPF_10GB_FD',
+    128: 'OFPPF_40GB_FD',
+    256: 'OFPPF_100GB_FD',
+    512: 'OFPPF_1TB_FD',
+    1024: 'OFPPF_OTHER',
+    2048: 'OFPPF_COPPER',
+    4096: 'OFPPF_FIBER',
+    8192: 'OFPPF_AUTONEG',
+    16384: 'OFPPF_PAUSE',
+    32768: 'OFPPF_PAUSE_ASYM',
+}
+
+# Identifiers from group ofp_port_mod_failed_code
+OFPPMFC_BAD_PORT = 0
+OFPPMFC_BAD_HW_ADDR = 1
+OFPPMFC_BAD_CONFIG = 2
+OFPPMFC_BAD_ADVERTISE = 3
+OFPPMFC_EPERM = 4
+
+ofp_port_mod_failed_code_map = {
+    0: 'OFPPMFC_BAD_PORT',
+    1: 'OFPPMFC_BAD_HW_ADDR',
+    2: 'OFPPMFC_BAD_CONFIG',
+    3: 'OFPPMFC_BAD_ADVERTISE',
+    4: 'OFPPMFC_EPERM',
+}
+
+# Identifiers from group ofp_port_no
+OFPP_ANY = 4294967295
+
+ofp_port_no_map = {
+    4294967295: 'OFPP_ANY',
+}
+
+# Identifiers from group ofp_port_reason
+OFPPR_ADD = 0
+OFPPR_DELETE = 1
+OFPPR_MODIFY = 2
+
+ofp_port_reason_map = {
+    0: 'OFPPR_ADD',
+    1: 'OFPPR_DELETE',
+    2: 'OFPPR_MODIFY',
+}
+
+# Identifiers from group ofp_port_state
+OFPPS_LINK_DOWN = 1
+OFPPS_BLOCKED = 2
+OFPPS_LIVE = 4
+
+ofp_port_state_map = {
+    1: 'OFPPS_LINK_DOWN',
+    2: 'OFPPS_BLOCKED',
+    4: 'OFPPS_LIVE',
+}
+
+# Identifiers from group ofp_queue_op_failed_code
+OFPQOFC_BAD_PORT = 0
+OFPQOFC_BAD_QUEUE = 1
+OFPQOFC_EPERM = 2
+
+ofp_queue_op_failed_code_map = {
+    0: 'OFPQOFC_BAD_PORT',
+    1: 'OFPQOFC_BAD_QUEUE',
+    2: 'OFPQOFC_EPERM',
+}
+
+# Identifiers from group ofp_queue_properties
+OFPQT_MIN_RATE = 1
+OFPQT_MAX_RATE = 2
+OFPQT_EXPERIMENTER = 65535
+
+ofp_queue_properties_map = {
+    1: 'OFPQT_MIN_RATE',
+    2: 'OFPQT_MAX_RATE',
+    65535: 'OFPQT_EXPERIMENTER',
+}
+
+# Identifiers from group ofp_role_request_failed_code
+OFPRRFC_STALE = 0
+OFPRRFC_UNSUP = 1
+OFPRRFC_BAD_ROLE = 2
+
+ofp_role_request_failed_code_map = {
+    0: 'OFPRRFC_STALE',
+    1: 'OFPRRFC_UNSUP',
+    2: 'OFPRRFC_BAD_ROLE',
+}
+
+# Identifiers from group ofp_switch_config_failed_code
+OFPSCFC_BAD_FLAGS = 0
+OFPSCFC_BAD_LEN = 1
+OFPSCFC_EPERM = 2
+
+ofp_switch_config_failed_code_map = {
+    0: 'OFPSCFC_BAD_FLAGS',
+    1: 'OFPSCFC_BAD_LEN',
+    2: 'OFPSCFC_EPERM',
+}
+
+# Identifiers from group ofp_table
+OFPTT_MAX = 254
+OFPTT_ALL = 255
+
+ofp_table_map = {
+    254: 'OFPTT_MAX',
+    255: 'OFPTT_ALL',
+}
+
+# Identifiers from group ofp_table_config
+OFPTC_DEPRECATED_MASK = 3
+
+ofp_table_config_map = {
+    3: 'OFPTC_DEPRECATED_MASK',
+}
+
+# Identifiers from group ofp_table_feature_prop_type
+OFPTFPT_INSTRUCTIONS = 0
+OFPTFPT_INSTRUCTIONS_MISS = 1
+OFPTFPT_NEXT_TABLES = 2
+OFPTFPT_NEXT_TABLES_MISS = 3
+OFPTFPT_WRITE_ACTIONS = 4
+OFPTFPT_WRITE_ACTIONS_MISS = 5
+OFPTFPT_APPLY_ACTIONS = 6
+OFPTFPT_APPLY_ACTIONS_MISS = 7
+OFPTFPT_MATCH = 8
+OFPTFPT_WILDCARDS = 10
+OFPTFPT_WRITE_SETFIELD = 12
+OFPTFPT_WRITE_SETFIELD_MISS = 13
+OFPTFPT_APPLY_SETFIELD = 14
+OFPTFPT_APPLY_SETFIELD_MISS = 15
+OFPTFPT_EXPERIMENTER = 65534
+OFPTFPT_EXPERIMENTER_MISS = 65535
+
+ofp_table_feature_prop_type_map = {
+    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',
+}
+
+# Identifiers from group ofp_table_features_failed_code
+OFPTFFC_BAD_TABLE = 0
+OFPTFFC_BAD_METADATA = 1
+OFPTFFC_BAD_TYPE = 2
+OFPTFFC_BAD_LEN = 3
+OFPTFFC_BAD_ARGUMENT = 4
+OFPTFFC_EPERM = 5
+
+ofp_table_features_failed_code_map = {
+    0: 'OFPTFFC_BAD_TABLE',
+    1: 'OFPTFFC_BAD_METADATA',
+    2: 'OFPTFFC_BAD_TYPE',
+    3: 'OFPTFFC_BAD_LEN',
+    4: 'OFPTFFC_BAD_ARGUMENT',
+    5: 'OFPTFFC_EPERM',
+}
+
+# Identifiers from group ofp_table_mod_failed_code
+OFPTMFC_BAD_TABLE = 0
+OFPTMFC_BAD_CONFIG = 1
+OFPTMFC_EPERM = 2
+
+ofp_table_mod_failed_code_map = {
+    0: 'OFPTMFC_BAD_TABLE',
+    1: 'OFPTMFC_BAD_CONFIG',
+    2: 'OFPTMFC_EPERM',
+}
+
+# Identifiers from group ofp_type
+OFPT_HELLO = 0
+OFPT_ERROR = 1
+OFPT_ECHO_REQUEST = 2
+OFPT_ECHO_REPLY = 3
+OFPT_EXPERIMENTER = 4
+OFPT_FEATURES_REQUEST = 5
+OFPT_FEATURES_REPLY = 6
+OFPT_GET_CONFIG_REQUEST = 7
+OFPT_GET_CONFIG_REPLY = 8
+OFPT_SET_CONFIG = 9
+OFPT_PACKET_IN = 10
+OFPT_FLOW_REMOVED = 11
+OFPT_PORT_STATUS = 12
+OFPT_PACKET_OUT = 13
+OFPT_FLOW_MOD = 14
+OFPT_GROUP_MOD = 15
+OFPT_PORT_MOD = 16
+OFPT_TABLE_MOD = 17
+OFPT_MULTIPART_REQUEST = 18
+OFPT_MULTIPART_REPLY = 19
+OFPT_BARRIER_REQUEST = 20
+OFPT_BARRIER_REPLY = 21
+OFPT_QUEUE_GET_CONFIG_REQUEST = 22
+OFPT_QUEUE_GET_CONFIG_REPLY = 23
+OFPT_ROLE_REQUEST = 24
+OFPT_ROLE_REPLY = 25
+OFPT_GET_ASYNC_REQUEST = 26
+OFPT_GET_ASYNC_REPLY = 27
+OFPT_SET_ASYNC = 28
+OFPT_METER_MOD = 29
+
+ofp_type_map = {
+    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',
+}
+
+# Identifiers from group ofp_vlan_id
+OFPVID_NONE = 0
+OFPVID_PRESENT = 4096
+
+ofp_vlan_id_map = {
+    0: 'OFPVID_NONE',
+    4096: 'OFPVID_PRESENT',
+}
+
diff --git a/src/python/loxi/of13/message.py b/src/python/loxi/of13/message.py
new file mode 100644
index 0000000..d6b1e5e
--- /dev/null
+++ b/src/python/loxi/of13/message.py
@@ -0,0 +1,6762 @@
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+
+# Automatically generated by LOXI from template message.py
+# Do not modify
+
+import struct
+import loxi
+import const
+import common
+import action # for unpack_list
+import instruction # for unpack_list
+import meter_band # for unpack_list
+import util
+import loxi.generic_util
+
+class Message(object):
+    version = const.OFP_VERSION
+    type = None # override in subclass
+    xid = None
+
+class aggregate_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REPLY
+    stats_type = 2
+
+    def __init__(self, xid=None, flags=None, packet_count=None, byte_count=None, flow_count=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if packet_count != None:
+            self.packet_count = packet_count
+        else:
+            self.packet_count = 0
+        if byte_count != None:
+            self.byte_count = byte_count
+        else:
+            self.byte_count = 0
+        if flow_count != None:
+            self.flow_count = flow_count
+        else:
+            self.flow_count = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!Q", self.packet_count))
+        packed.append(struct.pack("!Q", self.byte_count))
+        packed.append(struct.pack("!L", self.flow_count))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = aggregate_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 2)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.packet_count = reader.read('!Q')[0]
+        obj.byte_count = reader.read('!Q')[0]
+        obj.flow_count = reader.read('!L')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.packet_count != other.packet_count: return False
+        if self.byte_count != other.byte_count: return False
+        if self.flow_count != other.flow_count: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("aggregate_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("packet_count = ");
+                q.text("%#x" % self.packet_count)
+                q.text(","); q.breakable()
+                q.text("byte_count = ");
+                q.text("%#x" % self.byte_count)
+                q.text(","); q.breakable()
+                q.text("flow_count = ");
+                q.text("%#x" % self.flow_count)
+            q.breakable()
+        q.text('}')
+
+class aggregate_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REQUEST
+    stats_type = 2
+
+    def __init__(self, xid=None, flags=None, table_id=None, out_port=None, out_group=None, cookie=None, cookie_mask=None, match=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if out_port != None:
+            self.out_port = out_port
+        else:
+            self.out_port = 0
+        if out_group != None:
+            self.out_group = out_group
+        else:
+            self.out_group = 0
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if cookie_mask != None:
+            self.cookie_mask = cookie_mask
+        else:
+            self.cookie_mask = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append('\x00' * 3)
+        packed.append(struct.pack("!L", self.out_port))
+        packed.append(struct.pack("!L", self.out_group))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!Q", self.cookie_mask))
+        packed.append(self.match.pack())
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = aggregate_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 2)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.table_id = reader.read('!B')[0]
+        reader.skip(3)
+        obj.out_port = reader.read('!L')[0]
+        obj.out_group = reader.read('!L')[0]
+        reader.skip(4)
+        obj.cookie = reader.read('!Q')[0]
+        obj.cookie_mask = reader.read('!Q')[0]
+        obj.match = common.match.unpack(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.table_id != other.table_id: return False
+        if self.out_port != other.out_port: return False
+        if self.out_group != other.out_group: return False
+        if self.cookie != other.cookie: return False
+        if self.cookie_mask != other.cookie_mask: return False
+        if self.match != other.match: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("aggregate_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("out_port = ");
+                q.text(util.pretty_port(self.out_port))
+                q.text(","); q.breakable()
+                q.text("out_group = ");
+                q.text("%#x" % self.out_group)
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("cookie_mask = ");
+                q.text("%#x" % self.cookie_mask)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+            q.breakable()
+        q.text('}')
+
+class async_get_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_GET_ASYNC_REPLY
+
+    def __init__(self, xid=None, packet_in_mask_equal_master=None, packet_in_mask_slave=None, port_status_mask_equal_master=None, port_status_mask_slave=None, flow_removed_mask_equal_master=None, flow_removed_mask_slave=None):
+        self.xid = xid
+        if packet_in_mask_equal_master != None:
+            self.packet_in_mask_equal_master = packet_in_mask_equal_master
+        else:
+            self.packet_in_mask_equal_master = 0
+        if packet_in_mask_slave != None:
+            self.packet_in_mask_slave = packet_in_mask_slave
+        else:
+            self.packet_in_mask_slave = 0
+        if port_status_mask_equal_master != None:
+            self.port_status_mask_equal_master = port_status_mask_equal_master
+        else:
+            self.port_status_mask_equal_master = 0
+        if port_status_mask_slave != None:
+            self.port_status_mask_slave = port_status_mask_slave
+        else:
+            self.port_status_mask_slave = 0
+        if flow_removed_mask_equal_master != None:
+            self.flow_removed_mask_equal_master = flow_removed_mask_equal_master
+        else:
+            self.flow_removed_mask_equal_master = 0
+        if flow_removed_mask_slave != None:
+            self.flow_removed_mask_slave = flow_removed_mask_slave
+        else:
+            self.flow_removed_mask_slave = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.packet_in_mask_equal_master))
+        packed.append(struct.pack("!L", self.packet_in_mask_slave))
+        packed.append(struct.pack("!L", self.port_status_mask_equal_master))
+        packed.append(struct.pack("!L", self.port_status_mask_slave))
+        packed.append(struct.pack("!L", self.flow_removed_mask_equal_master))
+        packed.append(struct.pack("!L", self.flow_removed_mask_slave))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = async_get_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_GET_ASYNC_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.packet_in_mask_equal_master = reader.read('!L')[0]
+        obj.packet_in_mask_slave = reader.read('!L')[0]
+        obj.port_status_mask_equal_master = reader.read('!L')[0]
+        obj.port_status_mask_slave = reader.read('!L')[0]
+        obj.flow_removed_mask_equal_master = reader.read('!L')[0]
+        obj.flow_removed_mask_slave = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.packet_in_mask_equal_master != other.packet_in_mask_equal_master: return False
+        if self.packet_in_mask_slave != other.packet_in_mask_slave: return False
+        if self.port_status_mask_equal_master != other.port_status_mask_equal_master: return False
+        if self.port_status_mask_slave != other.port_status_mask_slave: return False
+        if self.flow_removed_mask_equal_master != other.flow_removed_mask_equal_master: return False
+        if self.flow_removed_mask_slave != other.flow_removed_mask_slave: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("async_get_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("packet_in_mask_equal_master = ");
+                q.text("%#x" % self.packet_in_mask_equal_master)
+                q.text(","); q.breakable()
+                q.text("packet_in_mask_slave = ");
+                q.text("%#x" % self.packet_in_mask_slave)
+                q.text(","); q.breakable()
+                q.text("port_status_mask_equal_master = ");
+                q.text("%#x" % self.port_status_mask_equal_master)
+                q.text(","); q.breakable()
+                q.text("port_status_mask_slave = ");
+                q.text("%#x" % self.port_status_mask_slave)
+                q.text(","); q.breakable()
+                q.text("flow_removed_mask_equal_master = ");
+                q.text("%#x" % self.flow_removed_mask_equal_master)
+                q.text(","); q.breakable()
+                q.text("flow_removed_mask_slave = ");
+                q.text("%#x" % self.flow_removed_mask_slave)
+            q.breakable()
+        q.text('}')
+
+class async_get_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_GET_ASYNC_REQUEST
+
+    def __init__(self, xid=None, packet_in_mask_equal_master=None, packet_in_mask_slave=None, port_status_mask_equal_master=None, port_status_mask_slave=None, flow_removed_mask_equal_master=None, flow_removed_mask_slave=None):
+        self.xid = xid
+        if packet_in_mask_equal_master != None:
+            self.packet_in_mask_equal_master = packet_in_mask_equal_master
+        else:
+            self.packet_in_mask_equal_master = 0
+        if packet_in_mask_slave != None:
+            self.packet_in_mask_slave = packet_in_mask_slave
+        else:
+            self.packet_in_mask_slave = 0
+        if port_status_mask_equal_master != None:
+            self.port_status_mask_equal_master = port_status_mask_equal_master
+        else:
+            self.port_status_mask_equal_master = 0
+        if port_status_mask_slave != None:
+            self.port_status_mask_slave = port_status_mask_slave
+        else:
+            self.port_status_mask_slave = 0
+        if flow_removed_mask_equal_master != None:
+            self.flow_removed_mask_equal_master = flow_removed_mask_equal_master
+        else:
+            self.flow_removed_mask_equal_master = 0
+        if flow_removed_mask_slave != None:
+            self.flow_removed_mask_slave = flow_removed_mask_slave
+        else:
+            self.flow_removed_mask_slave = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.packet_in_mask_equal_master))
+        packed.append(struct.pack("!L", self.packet_in_mask_slave))
+        packed.append(struct.pack("!L", self.port_status_mask_equal_master))
+        packed.append(struct.pack("!L", self.port_status_mask_slave))
+        packed.append(struct.pack("!L", self.flow_removed_mask_equal_master))
+        packed.append(struct.pack("!L", self.flow_removed_mask_slave))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = async_get_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_GET_ASYNC_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.packet_in_mask_equal_master = reader.read('!L')[0]
+        obj.packet_in_mask_slave = reader.read('!L')[0]
+        obj.port_status_mask_equal_master = reader.read('!L')[0]
+        obj.port_status_mask_slave = reader.read('!L')[0]
+        obj.flow_removed_mask_equal_master = reader.read('!L')[0]
+        obj.flow_removed_mask_slave = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.packet_in_mask_equal_master != other.packet_in_mask_equal_master: return False
+        if self.packet_in_mask_slave != other.packet_in_mask_slave: return False
+        if self.port_status_mask_equal_master != other.port_status_mask_equal_master: return False
+        if self.port_status_mask_slave != other.port_status_mask_slave: return False
+        if self.flow_removed_mask_equal_master != other.flow_removed_mask_equal_master: return False
+        if self.flow_removed_mask_slave != other.flow_removed_mask_slave: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("async_get_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("packet_in_mask_equal_master = ");
+                q.text("%#x" % self.packet_in_mask_equal_master)
+                q.text(","); q.breakable()
+                q.text("packet_in_mask_slave = ");
+                q.text("%#x" % self.packet_in_mask_slave)
+                q.text(","); q.breakable()
+                q.text("port_status_mask_equal_master = ");
+                q.text("%#x" % self.port_status_mask_equal_master)
+                q.text(","); q.breakable()
+                q.text("port_status_mask_slave = ");
+                q.text("%#x" % self.port_status_mask_slave)
+                q.text(","); q.breakable()
+                q.text("flow_removed_mask_equal_master = ");
+                q.text("%#x" % self.flow_removed_mask_equal_master)
+                q.text(","); q.breakable()
+                q.text("flow_removed_mask_slave = ");
+                q.text("%#x" % self.flow_removed_mask_slave)
+            q.breakable()
+        q.text('}')
+
+class async_set(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_SET_ASYNC
+
+    def __init__(self, xid=None, packet_in_mask_equal_master=None, packet_in_mask_slave=None, port_status_mask_equal_master=None, port_status_mask_slave=None, flow_removed_mask_equal_master=None, flow_removed_mask_slave=None):
+        self.xid = xid
+        if packet_in_mask_equal_master != None:
+            self.packet_in_mask_equal_master = packet_in_mask_equal_master
+        else:
+            self.packet_in_mask_equal_master = 0
+        if packet_in_mask_slave != None:
+            self.packet_in_mask_slave = packet_in_mask_slave
+        else:
+            self.packet_in_mask_slave = 0
+        if port_status_mask_equal_master != None:
+            self.port_status_mask_equal_master = port_status_mask_equal_master
+        else:
+            self.port_status_mask_equal_master = 0
+        if port_status_mask_slave != None:
+            self.port_status_mask_slave = port_status_mask_slave
+        else:
+            self.port_status_mask_slave = 0
+        if flow_removed_mask_equal_master != None:
+            self.flow_removed_mask_equal_master = flow_removed_mask_equal_master
+        else:
+            self.flow_removed_mask_equal_master = 0
+        if flow_removed_mask_slave != None:
+            self.flow_removed_mask_slave = flow_removed_mask_slave
+        else:
+            self.flow_removed_mask_slave = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.packet_in_mask_equal_master))
+        packed.append(struct.pack("!L", self.packet_in_mask_slave))
+        packed.append(struct.pack("!L", self.port_status_mask_equal_master))
+        packed.append(struct.pack("!L", self.port_status_mask_slave))
+        packed.append(struct.pack("!L", self.flow_removed_mask_equal_master))
+        packed.append(struct.pack("!L", self.flow_removed_mask_slave))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = async_set()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_SET_ASYNC)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.packet_in_mask_equal_master = reader.read('!L')[0]
+        obj.packet_in_mask_slave = reader.read('!L')[0]
+        obj.port_status_mask_equal_master = reader.read('!L')[0]
+        obj.port_status_mask_slave = reader.read('!L')[0]
+        obj.flow_removed_mask_equal_master = reader.read('!L')[0]
+        obj.flow_removed_mask_slave = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.packet_in_mask_equal_master != other.packet_in_mask_equal_master: return False
+        if self.packet_in_mask_slave != other.packet_in_mask_slave: return False
+        if self.port_status_mask_equal_master != other.port_status_mask_equal_master: return False
+        if self.port_status_mask_slave != other.port_status_mask_slave: return False
+        if self.flow_removed_mask_equal_master != other.flow_removed_mask_equal_master: return False
+        if self.flow_removed_mask_slave != other.flow_removed_mask_slave: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("async_set {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("packet_in_mask_equal_master = ");
+                q.text("%#x" % self.packet_in_mask_equal_master)
+                q.text(","); q.breakable()
+                q.text("packet_in_mask_slave = ");
+                q.text("%#x" % self.packet_in_mask_slave)
+                q.text(","); q.breakable()
+                q.text("port_status_mask_equal_master = ");
+                q.text("%#x" % self.port_status_mask_equal_master)
+                q.text(","); q.breakable()
+                q.text("port_status_mask_slave = ");
+                q.text("%#x" % self.port_status_mask_slave)
+                q.text(","); q.breakable()
+                q.text("flow_removed_mask_equal_master = ");
+                q.text("%#x" % self.flow_removed_mask_equal_master)
+                q.text(","); q.breakable()
+                q.text("flow_removed_mask_slave = ");
+                q.text("%#x" % self.flow_removed_mask_slave)
+            q.breakable()
+        q.text('}')
+
+class barrier_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_BARRIER_REPLY
+
+    def __init__(self, xid=None):
+        self.xid = xid
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = barrier_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_BARRIER_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("barrier_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+            q.breakable()
+        q.text('}')
+
+class barrier_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_BARRIER_REQUEST
+
+    def __init__(self, xid=None):
+        self.xid = xid
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = barrier_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_BARRIER_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("barrier_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+            q.breakable()
+        q.text('}')
+
+class bsn_get_interfaces_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_EXPERIMENTER
+    experimenter = 0x5c16c7
+    subtype = 10
+
+    def __init__(self, xid=None, interfaces=None):
+        self.xid = xid
+        if interfaces != None:
+            self.interfaces = interfaces
+        else:
+            self.interfaces = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        packed.append("".join([x.pack() for x in self.interfaces]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = bsn_get_interfaces_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_EXPERIMENTER)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 10)
+        obj.interfaces = loxi.generic_util.unpack_list(reader, common.bsn_interface.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.interfaces != other.interfaces: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_get_interfaces_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("interfaces = ");
+                q.pp(self.interfaces)
+            q.breakable()
+        q.text('}')
+
+class bsn_get_interfaces_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_EXPERIMENTER
+    experimenter = 0x5c16c7
+    subtype = 9
+
+    def __init__(self, xid=None):
+        self.xid = xid
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = bsn_get_interfaces_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_EXPERIMENTER)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 9)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_get_interfaces_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+            q.breakable()
+        q.text('}')
+
+class bsn_get_mirroring_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_EXPERIMENTER
+    experimenter = 0x5c16c7
+    subtype = 5
+
+    def __init__(self, xid=None, report_mirror_ports=None):
+        self.xid = xid
+        if report_mirror_ports != None:
+            self.report_mirror_ports = report_mirror_ports
+        else:
+            self.report_mirror_ports = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        packed.append(struct.pack("!B", self.report_mirror_ports))
+        packed.append('\x00' * 3)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = bsn_get_mirroring_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_EXPERIMENTER)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 5)
+        obj.report_mirror_ports = reader.read('!B')[0]
+        reader.skip(3)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.report_mirror_ports != other.report_mirror_ports: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_get_mirroring_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("report_mirror_ports = ");
+                q.text("%#x" % self.report_mirror_ports)
+            q.breakable()
+        q.text('}')
+
+class bsn_get_mirroring_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_EXPERIMENTER
+    experimenter = 0x5c16c7
+    subtype = 4
+
+    def __init__(self, xid=None, report_mirror_ports=None):
+        self.xid = xid
+        if report_mirror_ports != None:
+            self.report_mirror_ports = report_mirror_ports
+        else:
+            self.report_mirror_ports = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        packed.append(struct.pack("!B", self.report_mirror_ports))
+        packed.append('\x00' * 3)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = bsn_get_mirroring_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_EXPERIMENTER)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 4)
+        obj.report_mirror_ports = reader.read('!B')[0]
+        reader.skip(3)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.report_mirror_ports != other.report_mirror_ports: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_get_mirroring_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("report_mirror_ports = ");
+                q.text("%#x" % self.report_mirror_ports)
+            q.breakable()
+        q.text('}')
+
+class bsn_set_mirroring(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_EXPERIMENTER
+    experimenter = 0x5c16c7
+    subtype = 3
+
+    def __init__(self, xid=None, report_mirror_ports=None):
+        self.xid = xid
+        if report_mirror_ports != None:
+            self.report_mirror_ports = report_mirror_ports
+        else:
+            self.report_mirror_ports = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        packed.append(struct.pack("!B", self.report_mirror_ports))
+        packed.append('\x00' * 3)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = bsn_set_mirroring()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_EXPERIMENTER)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 3)
+        obj.report_mirror_ports = reader.read('!B')[0]
+        reader.skip(3)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.report_mirror_ports != other.report_mirror_ports: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_set_mirroring {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("report_mirror_ports = ");
+                q.text("%#x" % self.report_mirror_ports)
+            q.breakable()
+        q.text('}')
+
+class bsn_set_pktin_suppression(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_EXPERIMENTER
+    experimenter = 0x5c16c7
+    subtype = 11
+
+    def __init__(self, xid=None, enabled=None, idle_timeout=None, hard_timeout=None, priority=None, cookie=None):
+        self.xid = xid
+        if enabled != None:
+            self.enabled = enabled
+        else:
+            self.enabled = 0
+        if idle_timeout != None:
+            self.idle_timeout = idle_timeout
+        else:
+            self.idle_timeout = 0
+        if hard_timeout != None:
+            self.hard_timeout = hard_timeout
+        else:
+            self.hard_timeout = 0
+        if priority != None:
+            self.priority = priority
+        else:
+            self.priority = 0
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.experimenter))
+        packed.append(struct.pack("!L", self.subtype))
+        packed.append(struct.pack("!B", self.enabled))
+        packed.append('\x00' * 1)
+        packed.append(struct.pack("!H", self.idle_timeout))
+        packed.append(struct.pack("!H", self.hard_timeout))
+        packed.append(struct.pack("!H", self.priority))
+        packed.append(struct.pack("!Q", self.cookie))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = bsn_set_pktin_suppression()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_EXPERIMENTER)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _experimenter = reader.read('!L')[0]
+        assert(_experimenter == 0x5c16c7)
+        _subtype = reader.read('!L')[0]
+        assert(_subtype == 11)
+        obj.enabled = reader.read('!B')[0]
+        reader.skip(1)
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.cookie = reader.read('!Q')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.enabled != other.enabled: return False
+        if self.idle_timeout != other.idle_timeout: return False
+        if self.hard_timeout != other.hard_timeout: return False
+        if self.priority != other.priority: return False
+        if self.cookie != other.cookie: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("bsn_set_pktin_suppression {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("enabled = ");
+                q.text("%#x" % self.enabled)
+                q.text(","); q.breakable()
+                q.text("idle_timeout = ");
+                q.text("%#x" % self.idle_timeout)
+                q.text(","); q.breakable()
+                q.text("hard_timeout = ");
+                q.text("%#x" % self.hard_timeout)
+                q.text(","); q.breakable()
+                q.text("priority = ");
+                q.text("%#x" % self.priority)
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+            q.breakable()
+        q.text('}')
+
+class desc_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REPLY
+    stats_type = 0
+
+    def __init__(self, xid=None, flags=None, mfr_desc=None, hw_desc=None, sw_desc=None, serial_num=None, dp_desc=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if mfr_desc != None:
+            self.mfr_desc = mfr_desc
+        else:
+            self.mfr_desc = ""
+        if hw_desc != None:
+            self.hw_desc = hw_desc
+        else:
+            self.hw_desc = ""
+        if sw_desc != None:
+            self.sw_desc = sw_desc
+        else:
+            self.sw_desc = ""
+        if serial_num != None:
+            self.serial_num = serial_num
+        else:
+            self.serial_num = ""
+        if dp_desc != None:
+            self.dp_desc = dp_desc
+        else:
+            self.dp_desc = ""
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!256s", self.mfr_desc))
+        packed.append(struct.pack("!256s", self.hw_desc))
+        packed.append(struct.pack("!256s", self.sw_desc))
+        packed.append(struct.pack("!32s", self.serial_num))
+        packed.append(struct.pack("!256s", self.dp_desc))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = desc_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 0)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.mfr_desc = reader.read("!256s")[0].rstrip("\x00")
+        obj.hw_desc = reader.read("!256s")[0].rstrip("\x00")
+        obj.sw_desc = reader.read("!256s")[0].rstrip("\x00")
+        obj.serial_num = reader.read("!32s")[0].rstrip("\x00")
+        obj.dp_desc = reader.read("!256s")[0].rstrip("\x00")
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.mfr_desc != other.mfr_desc: return False
+        if self.hw_desc != other.hw_desc: return False
+        if self.sw_desc != other.sw_desc: return False
+        if self.serial_num != other.serial_num: return False
+        if self.dp_desc != other.dp_desc: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("desc_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("mfr_desc = ");
+                q.pp(self.mfr_desc)
+                q.text(","); q.breakable()
+                q.text("hw_desc = ");
+                q.pp(self.hw_desc)
+                q.text(","); q.breakable()
+                q.text("sw_desc = ");
+                q.pp(self.sw_desc)
+                q.text(","); q.breakable()
+                q.text("serial_num = ");
+                q.pp(self.serial_num)
+                q.text(","); q.breakable()
+                q.text("dp_desc = ");
+                q.pp(self.dp_desc)
+            q.breakable()
+        q.text('}')
+
+class desc_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REQUEST
+    stats_type = 0
+
+    def __init__(self, xid=None, flags=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = desc_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 0)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("desc_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+            q.breakable()
+        q.text('}')
+
+class echo_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_ECHO_REPLY
+
+    def __init__(self, xid=None, data=None):
+        self.xid = xid
+        if data != None:
+            self.data = data
+        else:
+            self.data = ""
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(self.data)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = echo_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_ECHO_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.data = str(reader.read_all())
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.data != other.data: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("echo_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("data = ");
+                q.pp(self.data)
+            q.breakable()
+        q.text('}')
+
+class echo_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_ECHO_REQUEST
+
+    def __init__(self, xid=None, data=None):
+        self.xid = xid
+        if data != None:
+            self.data = data
+        else:
+            self.data = ""
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(self.data)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = echo_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_ECHO_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.data = str(reader.read_all())
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.data != other.data: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("echo_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("data = ");
+                q.pp(self.data)
+            q.breakable()
+        q.text('}')
+
+class error_msg(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_ERROR
+
+    def __init__(self, xid=None, err_type=None, code=None, data=None):
+        self.xid = xid
+        if err_type != None:
+            self.err_type = err_type
+        else:
+            self.err_type = 0
+        if code != None:
+            self.code = code
+        else:
+            self.code = 0
+        if data != None:
+            self.data = data
+        else:
+            self.data = ""
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.err_type))
+        packed.append(struct.pack("!H", self.code))
+        packed.append(self.data)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = error_msg()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_ERROR)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.err_type = reader.read('!H')[0]
+        obj.code = reader.read('!H')[0]
+        obj.data = str(reader.read_all())
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.err_type != other.err_type: return False
+        if self.code != other.code: return False
+        if self.data != other.data: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("error_msg {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("err_type = ");
+                q.text("%#x" % self.err_type)
+                q.text(","); q.breakable()
+                q.text("code = ");
+                q.text("%#x" % self.code)
+                q.text(","); q.breakable()
+                q.text("data = ");
+                q.pp(self.data)
+            q.breakable()
+        q.text('}')
+
+class features_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_FEATURES_REPLY
+
+    def __init__(self, xid=None, datapath_id=None, n_buffers=None, n_tables=None, auxiliary_id=None, capabilities=None, reserved=None):
+        self.xid = xid
+        if datapath_id != None:
+            self.datapath_id = datapath_id
+        else:
+            self.datapath_id = 0
+        if n_buffers != None:
+            self.n_buffers = n_buffers
+        else:
+            self.n_buffers = 0
+        if n_tables != None:
+            self.n_tables = n_tables
+        else:
+            self.n_tables = 0
+        if auxiliary_id != None:
+            self.auxiliary_id = auxiliary_id
+        else:
+            self.auxiliary_id = 0
+        if capabilities != None:
+            self.capabilities = capabilities
+        else:
+            self.capabilities = 0
+        if reserved != None:
+            self.reserved = reserved
+        else:
+            self.reserved = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!Q", self.datapath_id))
+        packed.append(struct.pack("!L", self.n_buffers))
+        packed.append(struct.pack("!B", self.n_tables))
+        packed.append(struct.pack("!B", self.auxiliary_id))
+        packed.append('\x00' * 2)
+        packed.append(struct.pack("!L", self.capabilities))
+        packed.append(struct.pack("!L", self.reserved))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = features_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FEATURES_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.datapath_id = reader.read('!Q')[0]
+        obj.n_buffers = reader.read('!L')[0]
+        obj.n_tables = reader.read('!B')[0]
+        obj.auxiliary_id = reader.read('!B')[0]
+        reader.skip(2)
+        obj.capabilities = reader.read('!L')[0]
+        obj.reserved = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.datapath_id != other.datapath_id: return False
+        if self.n_buffers != other.n_buffers: return False
+        if self.n_tables != other.n_tables: return False
+        if self.auxiliary_id != other.auxiliary_id: return False
+        if self.capabilities != other.capabilities: return False
+        if self.reserved != other.reserved: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("features_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("datapath_id = ");
+                q.text("%#x" % self.datapath_id)
+                q.text(","); q.breakable()
+                q.text("n_buffers = ");
+                q.text("%#x" % self.n_buffers)
+                q.text(","); q.breakable()
+                q.text("n_tables = ");
+                q.text("%#x" % self.n_tables)
+                q.text(","); q.breakable()
+                q.text("auxiliary_id = ");
+                q.text("%#x" % self.auxiliary_id)
+                q.text(","); q.breakable()
+                q.text("capabilities = ");
+                q.text("%#x" % self.capabilities)
+                q.text(","); q.breakable()
+                q.text("reserved = ");
+                q.text("%#x" % self.reserved)
+            q.breakable()
+        q.text('}')
+
+class features_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_FEATURES_REQUEST
+
+    def __init__(self, xid=None):
+        self.xid = xid
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = features_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FEATURES_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("features_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+            q.breakable()
+        q.text('}')
+
+class flow_add(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_FLOW_MOD
+    _command = const.OFPFC_ADD
+
+    def __init__(self, xid=None, cookie=None, cookie_mask=None, table_id=None, idle_timeout=None, hard_timeout=None, priority=None, buffer_id=None, out_port=None, out_group=None, flags=None, match=None, instructions=None):
+        self.xid = xid
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if cookie_mask != None:
+            self.cookie_mask = cookie_mask
+        else:
+            self.cookie_mask = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if idle_timeout != None:
+            self.idle_timeout = idle_timeout
+        else:
+            self.idle_timeout = 0
+        if hard_timeout != None:
+            self.hard_timeout = hard_timeout
+        else:
+            self.hard_timeout = 0
+        if priority != None:
+            self.priority = priority
+        else:
+            self.priority = 0
+        if buffer_id != None:
+            self.buffer_id = buffer_id
+        else:
+            self.buffer_id = 0
+        if out_port != None:
+            self.out_port = out_port
+        else:
+            self.out_port = 0
+        if out_group != None:
+            self.out_group = out_group
+        else:
+            self.out_group = 0
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+        if instructions != None:
+            self.instructions = instructions
+        else:
+            self.instructions = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!Q", self.cookie_mask))
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append(struct.pack("!B", self._command))
+        packed.append(struct.pack("!H", self.idle_timeout))
+        packed.append(struct.pack("!H", self.hard_timeout))
+        packed.append(struct.pack("!H", self.priority))
+        packed.append(struct.pack("!L", self.buffer_id))
+        packed.append(struct.pack("!L", self.out_port))
+        packed.append(struct.pack("!L", self.out_group))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 2)
+        packed.append(self.match.pack())
+        packed.append("".join([x.pack() for x in self.instructions]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = flow_add()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FLOW_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.cookie = reader.read('!Q')[0]
+        obj.cookie_mask = reader.read('!Q')[0]
+        obj.table_id = reader.read('!B')[0]
+        __command = reader.read('!B')[0]
+        assert(__command == const.OFPFC_ADD)
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.out_port = reader.read('!L')[0]
+        obj.out_group = reader.read('!L')[0]
+        obj.flags = reader.read('!H')[0]
+        reader.skip(2)
+        obj.match = common.match.unpack(reader)
+        obj.instructions = instruction.unpack_list(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.cookie != other.cookie: return False
+        if self.cookie_mask != other.cookie_mask: return False
+        if self.table_id != other.table_id: return False
+        if self.idle_timeout != other.idle_timeout: return False
+        if self.hard_timeout != other.hard_timeout: return False
+        if self.priority != other.priority: return False
+        if self.buffer_id != other.buffer_id: return False
+        if self.out_port != other.out_port: return False
+        if self.out_group != other.out_group: return False
+        if self.flags != other.flags: return False
+        if self.match != other.match: return False
+        if self.instructions != other.instructions: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_add {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("cookie_mask = ");
+                q.text("%#x" % self.cookie_mask)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("idle_timeout = ");
+                q.text("%#x" % self.idle_timeout)
+                q.text(","); q.breakable()
+                q.text("hard_timeout = ");
+                q.text("%#x" % self.hard_timeout)
+                q.text(","); q.breakable()
+                q.text("priority = ");
+                q.text("%#x" % self.priority)
+                q.text(","); q.breakable()
+                q.text("buffer_id = ");
+                q.text("%#x" % self.buffer_id)
+                q.text(","); q.breakable()
+                q.text("out_port = ");
+                q.text(util.pretty_port(self.out_port))
+                q.text(","); q.breakable()
+                q.text("out_group = ");
+                q.text("%#x" % self.out_group)
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+                q.text(","); q.breakable()
+                q.text("instructions = ");
+                q.pp(self.instructions)
+            q.breakable()
+        q.text('}')
+
+class flow_delete(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_FLOW_MOD
+    _command = const.OFPFC_DELETE
+
+    def __init__(self, xid=None, cookie=None, cookie_mask=None, table_id=None, idle_timeout=None, hard_timeout=None, priority=None, buffer_id=None, out_port=None, out_group=None, flags=None, match=None, instructions=None):
+        self.xid = xid
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if cookie_mask != None:
+            self.cookie_mask = cookie_mask
+        else:
+            self.cookie_mask = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if idle_timeout != None:
+            self.idle_timeout = idle_timeout
+        else:
+            self.idle_timeout = 0
+        if hard_timeout != None:
+            self.hard_timeout = hard_timeout
+        else:
+            self.hard_timeout = 0
+        if priority != None:
+            self.priority = priority
+        else:
+            self.priority = 0
+        if buffer_id != None:
+            self.buffer_id = buffer_id
+        else:
+            self.buffer_id = 0
+        if out_port != None:
+            self.out_port = out_port
+        else:
+            self.out_port = 0
+        if out_group != None:
+            self.out_group = out_group
+        else:
+            self.out_group = 0
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+        if instructions != None:
+            self.instructions = instructions
+        else:
+            self.instructions = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!Q", self.cookie_mask))
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append(struct.pack("!B", self._command))
+        packed.append(struct.pack("!H", self.idle_timeout))
+        packed.append(struct.pack("!H", self.hard_timeout))
+        packed.append(struct.pack("!H", self.priority))
+        packed.append(struct.pack("!L", self.buffer_id))
+        packed.append(struct.pack("!L", self.out_port))
+        packed.append(struct.pack("!L", self.out_group))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 2)
+        packed.append(self.match.pack())
+        packed.append("".join([x.pack() for x in self.instructions]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = flow_delete()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FLOW_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.cookie = reader.read('!Q')[0]
+        obj.cookie_mask = reader.read('!Q')[0]
+        obj.table_id = reader.read('!B')[0]
+        __command = reader.read('!B')[0]
+        assert(__command == const.OFPFC_DELETE)
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.out_port = reader.read('!L')[0]
+        obj.out_group = reader.read('!L')[0]
+        obj.flags = reader.read('!H')[0]
+        reader.skip(2)
+        obj.match = common.match.unpack(reader)
+        obj.instructions = instruction.unpack_list(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.cookie != other.cookie: return False
+        if self.cookie_mask != other.cookie_mask: return False
+        if self.table_id != other.table_id: return False
+        if self.idle_timeout != other.idle_timeout: return False
+        if self.hard_timeout != other.hard_timeout: return False
+        if self.priority != other.priority: return False
+        if self.buffer_id != other.buffer_id: return False
+        if self.out_port != other.out_port: return False
+        if self.out_group != other.out_group: return False
+        if self.flags != other.flags: return False
+        if self.match != other.match: return False
+        if self.instructions != other.instructions: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_delete {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("cookie_mask = ");
+                q.text("%#x" % self.cookie_mask)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("idle_timeout = ");
+                q.text("%#x" % self.idle_timeout)
+                q.text(","); q.breakable()
+                q.text("hard_timeout = ");
+                q.text("%#x" % self.hard_timeout)
+                q.text(","); q.breakable()
+                q.text("priority = ");
+                q.text("%#x" % self.priority)
+                q.text(","); q.breakable()
+                q.text("buffer_id = ");
+                q.text("%#x" % self.buffer_id)
+                q.text(","); q.breakable()
+                q.text("out_port = ");
+                q.text(util.pretty_port(self.out_port))
+                q.text(","); q.breakable()
+                q.text("out_group = ");
+                q.text("%#x" % self.out_group)
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+                q.text(","); q.breakable()
+                q.text("instructions = ");
+                q.pp(self.instructions)
+            q.breakable()
+        q.text('}')
+
+class flow_delete_strict(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_FLOW_MOD
+    _command = const.OFPFC_DELETE_STRICT
+
+    def __init__(self, xid=None, cookie=None, cookie_mask=None, table_id=None, idle_timeout=None, hard_timeout=None, priority=None, buffer_id=None, out_port=None, out_group=None, flags=None, match=None, instructions=None):
+        self.xid = xid
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if cookie_mask != None:
+            self.cookie_mask = cookie_mask
+        else:
+            self.cookie_mask = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if idle_timeout != None:
+            self.idle_timeout = idle_timeout
+        else:
+            self.idle_timeout = 0
+        if hard_timeout != None:
+            self.hard_timeout = hard_timeout
+        else:
+            self.hard_timeout = 0
+        if priority != None:
+            self.priority = priority
+        else:
+            self.priority = 0
+        if buffer_id != None:
+            self.buffer_id = buffer_id
+        else:
+            self.buffer_id = 0
+        if out_port != None:
+            self.out_port = out_port
+        else:
+            self.out_port = 0
+        if out_group != None:
+            self.out_group = out_group
+        else:
+            self.out_group = 0
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+        if instructions != None:
+            self.instructions = instructions
+        else:
+            self.instructions = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!Q", self.cookie_mask))
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append(struct.pack("!B", self._command))
+        packed.append(struct.pack("!H", self.idle_timeout))
+        packed.append(struct.pack("!H", self.hard_timeout))
+        packed.append(struct.pack("!H", self.priority))
+        packed.append(struct.pack("!L", self.buffer_id))
+        packed.append(struct.pack("!L", self.out_port))
+        packed.append(struct.pack("!L", self.out_group))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 2)
+        packed.append(self.match.pack())
+        packed.append("".join([x.pack() for x in self.instructions]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = flow_delete_strict()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FLOW_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.cookie = reader.read('!Q')[0]
+        obj.cookie_mask = reader.read('!Q')[0]
+        obj.table_id = reader.read('!B')[0]
+        __command = reader.read('!B')[0]
+        assert(__command == const.OFPFC_DELETE_STRICT)
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.out_port = reader.read('!L')[0]
+        obj.out_group = reader.read('!L')[0]
+        obj.flags = reader.read('!H')[0]
+        reader.skip(2)
+        obj.match = common.match.unpack(reader)
+        obj.instructions = instruction.unpack_list(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.cookie != other.cookie: return False
+        if self.cookie_mask != other.cookie_mask: return False
+        if self.table_id != other.table_id: return False
+        if self.idle_timeout != other.idle_timeout: return False
+        if self.hard_timeout != other.hard_timeout: return False
+        if self.priority != other.priority: return False
+        if self.buffer_id != other.buffer_id: return False
+        if self.out_port != other.out_port: return False
+        if self.out_group != other.out_group: return False
+        if self.flags != other.flags: return False
+        if self.match != other.match: return False
+        if self.instructions != other.instructions: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_delete_strict {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("cookie_mask = ");
+                q.text("%#x" % self.cookie_mask)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("idle_timeout = ");
+                q.text("%#x" % self.idle_timeout)
+                q.text(","); q.breakable()
+                q.text("hard_timeout = ");
+                q.text("%#x" % self.hard_timeout)
+                q.text(","); q.breakable()
+                q.text("priority = ");
+                q.text("%#x" % self.priority)
+                q.text(","); q.breakable()
+                q.text("buffer_id = ");
+                q.text("%#x" % self.buffer_id)
+                q.text(","); q.breakable()
+                q.text("out_port = ");
+                q.text(util.pretty_port(self.out_port))
+                q.text(","); q.breakable()
+                q.text("out_group = ");
+                q.text("%#x" % self.out_group)
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+                q.text(","); q.breakable()
+                q.text("instructions = ");
+                q.pp(self.instructions)
+            q.breakable()
+        q.text('}')
+
+class flow_modify(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_FLOW_MOD
+    _command = const.OFPFC_MODIFY
+
+    def __init__(self, xid=None, cookie=None, cookie_mask=None, table_id=None, idle_timeout=None, hard_timeout=None, priority=None, buffer_id=None, out_port=None, out_group=None, flags=None, match=None, instructions=None):
+        self.xid = xid
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if cookie_mask != None:
+            self.cookie_mask = cookie_mask
+        else:
+            self.cookie_mask = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if idle_timeout != None:
+            self.idle_timeout = idle_timeout
+        else:
+            self.idle_timeout = 0
+        if hard_timeout != None:
+            self.hard_timeout = hard_timeout
+        else:
+            self.hard_timeout = 0
+        if priority != None:
+            self.priority = priority
+        else:
+            self.priority = 0
+        if buffer_id != None:
+            self.buffer_id = buffer_id
+        else:
+            self.buffer_id = 0
+        if out_port != None:
+            self.out_port = out_port
+        else:
+            self.out_port = 0
+        if out_group != None:
+            self.out_group = out_group
+        else:
+            self.out_group = 0
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+        if instructions != None:
+            self.instructions = instructions
+        else:
+            self.instructions = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!Q", self.cookie_mask))
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append(struct.pack("!B", self._command))
+        packed.append(struct.pack("!H", self.idle_timeout))
+        packed.append(struct.pack("!H", self.hard_timeout))
+        packed.append(struct.pack("!H", self.priority))
+        packed.append(struct.pack("!L", self.buffer_id))
+        packed.append(struct.pack("!L", self.out_port))
+        packed.append(struct.pack("!L", self.out_group))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 2)
+        packed.append(self.match.pack())
+        packed.append("".join([x.pack() for x in self.instructions]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = flow_modify()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FLOW_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.cookie = reader.read('!Q')[0]
+        obj.cookie_mask = reader.read('!Q')[0]
+        obj.table_id = reader.read('!B')[0]
+        __command = reader.read('!B')[0]
+        assert(__command == const.OFPFC_MODIFY)
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.out_port = reader.read('!L')[0]
+        obj.out_group = reader.read('!L')[0]
+        obj.flags = reader.read('!H')[0]
+        reader.skip(2)
+        obj.match = common.match.unpack(reader)
+        obj.instructions = instruction.unpack_list(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.cookie != other.cookie: return False
+        if self.cookie_mask != other.cookie_mask: return False
+        if self.table_id != other.table_id: return False
+        if self.idle_timeout != other.idle_timeout: return False
+        if self.hard_timeout != other.hard_timeout: return False
+        if self.priority != other.priority: return False
+        if self.buffer_id != other.buffer_id: return False
+        if self.out_port != other.out_port: return False
+        if self.out_group != other.out_group: return False
+        if self.flags != other.flags: return False
+        if self.match != other.match: return False
+        if self.instructions != other.instructions: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_modify {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("cookie_mask = ");
+                q.text("%#x" % self.cookie_mask)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("idle_timeout = ");
+                q.text("%#x" % self.idle_timeout)
+                q.text(","); q.breakable()
+                q.text("hard_timeout = ");
+                q.text("%#x" % self.hard_timeout)
+                q.text(","); q.breakable()
+                q.text("priority = ");
+                q.text("%#x" % self.priority)
+                q.text(","); q.breakable()
+                q.text("buffer_id = ");
+                q.text("%#x" % self.buffer_id)
+                q.text(","); q.breakable()
+                q.text("out_port = ");
+                q.text(util.pretty_port(self.out_port))
+                q.text(","); q.breakable()
+                q.text("out_group = ");
+                q.text("%#x" % self.out_group)
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+                q.text(","); q.breakable()
+                q.text("instructions = ");
+                q.pp(self.instructions)
+            q.breakable()
+        q.text('}')
+
+class flow_modify_strict(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_FLOW_MOD
+    _command = const.OFPFC_MODIFY_STRICT
+
+    def __init__(self, xid=None, cookie=None, cookie_mask=None, table_id=None, idle_timeout=None, hard_timeout=None, priority=None, buffer_id=None, out_port=None, out_group=None, flags=None, match=None, instructions=None):
+        self.xid = xid
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if cookie_mask != None:
+            self.cookie_mask = cookie_mask
+        else:
+            self.cookie_mask = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if idle_timeout != None:
+            self.idle_timeout = idle_timeout
+        else:
+            self.idle_timeout = 0
+        if hard_timeout != None:
+            self.hard_timeout = hard_timeout
+        else:
+            self.hard_timeout = 0
+        if priority != None:
+            self.priority = priority
+        else:
+            self.priority = 0
+        if buffer_id != None:
+            self.buffer_id = buffer_id
+        else:
+            self.buffer_id = 0
+        if out_port != None:
+            self.out_port = out_port
+        else:
+            self.out_port = 0
+        if out_group != None:
+            self.out_group = out_group
+        else:
+            self.out_group = 0
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+        if instructions != None:
+            self.instructions = instructions
+        else:
+            self.instructions = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!Q", self.cookie_mask))
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append(struct.pack("!B", self._command))
+        packed.append(struct.pack("!H", self.idle_timeout))
+        packed.append(struct.pack("!H", self.hard_timeout))
+        packed.append(struct.pack("!H", self.priority))
+        packed.append(struct.pack("!L", self.buffer_id))
+        packed.append(struct.pack("!L", self.out_port))
+        packed.append(struct.pack("!L", self.out_group))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 2)
+        packed.append(self.match.pack())
+        packed.append("".join([x.pack() for x in self.instructions]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = flow_modify_strict()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FLOW_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.cookie = reader.read('!Q')[0]
+        obj.cookie_mask = reader.read('!Q')[0]
+        obj.table_id = reader.read('!B')[0]
+        __command = reader.read('!B')[0]
+        assert(__command == const.OFPFC_MODIFY_STRICT)
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.out_port = reader.read('!L')[0]
+        obj.out_group = reader.read('!L')[0]
+        obj.flags = reader.read('!H')[0]
+        reader.skip(2)
+        obj.match = common.match.unpack(reader)
+        obj.instructions = instruction.unpack_list(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.cookie != other.cookie: return False
+        if self.cookie_mask != other.cookie_mask: return False
+        if self.table_id != other.table_id: return False
+        if self.idle_timeout != other.idle_timeout: return False
+        if self.hard_timeout != other.hard_timeout: return False
+        if self.priority != other.priority: return False
+        if self.buffer_id != other.buffer_id: return False
+        if self.out_port != other.out_port: return False
+        if self.out_group != other.out_group: return False
+        if self.flags != other.flags: return False
+        if self.match != other.match: return False
+        if self.instructions != other.instructions: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_modify_strict {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("cookie_mask = ");
+                q.text("%#x" % self.cookie_mask)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("idle_timeout = ");
+                q.text("%#x" % self.idle_timeout)
+                q.text(","); q.breakable()
+                q.text("hard_timeout = ");
+                q.text("%#x" % self.hard_timeout)
+                q.text(","); q.breakable()
+                q.text("priority = ");
+                q.text("%#x" % self.priority)
+                q.text(","); q.breakable()
+                q.text("buffer_id = ");
+                q.text("%#x" % self.buffer_id)
+                q.text(","); q.breakable()
+                q.text("out_port = ");
+                q.text(util.pretty_port(self.out_port))
+                q.text(","); q.breakable()
+                q.text("out_group = ");
+                q.text("%#x" % self.out_group)
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+                q.text(","); q.breakable()
+                q.text("instructions = ");
+                q.pp(self.instructions)
+            q.breakable()
+        q.text('}')
+
+class flow_removed(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_FLOW_REMOVED
+
+    def __init__(self, xid=None, cookie=None, priority=None, reason=None, table_id=None, duration_sec=None, duration_nsec=None, idle_timeout=None, hard_timeout=None, packet_count=None, byte_count=None, match=None):
+        self.xid = xid
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if priority != None:
+            self.priority = priority
+        else:
+            self.priority = 0
+        if reason != None:
+            self.reason = reason
+        else:
+            self.reason = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if duration_sec != None:
+            self.duration_sec = duration_sec
+        else:
+            self.duration_sec = 0
+        if duration_nsec != None:
+            self.duration_nsec = duration_nsec
+        else:
+            self.duration_nsec = 0
+        if idle_timeout != None:
+            self.idle_timeout = idle_timeout
+        else:
+            self.idle_timeout = 0
+        if hard_timeout != None:
+            self.hard_timeout = hard_timeout
+        else:
+            self.hard_timeout = 0
+        if packet_count != None:
+            self.packet_count = packet_count
+        else:
+            self.packet_count = 0
+        if byte_count != None:
+            self.byte_count = byte_count
+        else:
+            self.byte_count = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!H", self.priority))
+        packed.append(struct.pack("!B", self.reason))
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append(struct.pack("!L", self.duration_sec))
+        packed.append(struct.pack("!L", self.duration_nsec))
+        packed.append(struct.pack("!H", self.idle_timeout))
+        packed.append(struct.pack("!H", self.hard_timeout))
+        packed.append(struct.pack("!Q", self.packet_count))
+        packed.append(struct.pack("!Q", self.byte_count))
+        packed.append(self.match.pack())
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = flow_removed()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_FLOW_REMOVED)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.cookie = reader.read('!Q')[0]
+        obj.priority = reader.read('!H')[0]
+        obj.reason = reader.read('!B')[0]
+        obj.table_id = reader.read('!B')[0]
+        obj.duration_sec = reader.read('!L')[0]
+        obj.duration_nsec = reader.read('!L')[0]
+        obj.idle_timeout = reader.read('!H')[0]
+        obj.hard_timeout = reader.read('!H')[0]
+        obj.packet_count = reader.read('!Q')[0]
+        obj.byte_count = reader.read('!Q')[0]
+        obj.match = common.match.unpack(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.cookie != other.cookie: return False
+        if self.priority != other.priority: return False
+        if self.reason != other.reason: return False
+        if self.table_id != other.table_id: return False
+        if self.duration_sec != other.duration_sec: return False
+        if self.duration_nsec != other.duration_nsec: return False
+        if self.idle_timeout != other.idle_timeout: return False
+        if self.hard_timeout != other.hard_timeout: return False
+        if self.packet_count != other.packet_count: return False
+        if self.byte_count != other.byte_count: return False
+        if self.match != other.match: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_removed {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("priority = ");
+                q.text("%#x" % self.priority)
+                q.text(","); q.breakable()
+                q.text("reason = ");
+                q.text("%#x" % self.reason)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("duration_sec = ");
+                q.text("%#x" % self.duration_sec)
+                q.text(","); q.breakable()
+                q.text("duration_nsec = ");
+                q.text("%#x" % self.duration_nsec)
+                q.text(","); q.breakable()
+                q.text("idle_timeout = ");
+                q.text("%#x" % self.idle_timeout)
+                q.text(","); q.breakable()
+                q.text("hard_timeout = ");
+                q.text("%#x" % self.hard_timeout)
+                q.text(","); q.breakable()
+                q.text("packet_count = ");
+                q.text("%#x" % self.packet_count)
+                q.text(","); q.breakable()
+                q.text("byte_count = ");
+                q.text("%#x" % self.byte_count)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+            q.breakable()
+        q.text('}')
+
+class flow_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REPLY
+    stats_type = 1
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.entries]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = flow_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 1)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.entries = common.unpack_list_flow_stats_entry(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.entries != other.entries: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("entries = ");
+                q.pp(self.entries)
+            q.breakable()
+        q.text('}')
+
+class flow_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REQUEST
+    stats_type = 1
+
+    def __init__(self, xid=None, flags=None, table_id=None, out_port=None, out_group=None, cookie=None, cookie_mask=None, match=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if out_port != None:
+            self.out_port = out_port
+        else:
+            self.out_port = 0
+        if out_group != None:
+            self.out_group = out_group
+        else:
+            self.out_group = 0
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if cookie_mask != None:
+            self.cookie_mask = cookie_mask
+        else:
+            self.cookie_mask = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append('\x00' * 3)
+        packed.append(struct.pack("!L", self.out_port))
+        packed.append(struct.pack("!L", self.out_group))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(struct.pack("!Q", self.cookie_mask))
+        packed.append(self.match.pack())
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = flow_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 1)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.table_id = reader.read('!B')[0]
+        reader.skip(3)
+        obj.out_port = reader.read('!L')[0]
+        obj.out_group = reader.read('!L')[0]
+        reader.skip(4)
+        obj.cookie = reader.read('!Q')[0]
+        obj.cookie_mask = reader.read('!Q')[0]
+        obj.match = common.match.unpack(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.table_id != other.table_id: return False
+        if self.out_port != other.out_port: return False
+        if self.out_group != other.out_group: return False
+        if self.cookie != other.cookie: return False
+        if self.cookie_mask != other.cookie_mask: return False
+        if self.match != other.match: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("flow_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("out_port = ");
+                q.text(util.pretty_port(self.out_port))
+                q.text(","); q.breakable()
+                q.text("out_group = ");
+                q.text("%#x" % self.out_group)
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("cookie_mask = ");
+                q.text("%#x" % self.cookie_mask)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+            q.breakable()
+        q.text('}')
+
+class get_config_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_GET_CONFIG_REPLY
+
+    def __init__(self, xid=None, flags=None, miss_send_len=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if miss_send_len != None:
+            self.miss_send_len = miss_send_len
+        else:
+            self.miss_send_len = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append(struct.pack("!H", self.miss_send_len))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = get_config_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_GET_CONFIG_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.flags = reader.read('!H')[0]
+        obj.miss_send_len = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.miss_send_len != other.miss_send_len: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("get_config_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("miss_send_len = ");
+                q.text("%#x" % self.miss_send_len)
+            q.breakable()
+        q.text('}')
+
+class get_config_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_GET_CONFIG_REQUEST
+
+    def __init__(self, xid=None):
+        self.xid = xid
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = get_config_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_GET_CONFIG_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("get_config_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+            q.breakable()
+        q.text('}')
+
+class group_desc_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REPLY
+    stats_type = 7
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.entries]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = group_desc_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 7)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.entries = common.unpack_list_group_desc_stats_entry(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.entries != other.entries: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group_desc_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("entries = ");
+                q.pp(self.entries)
+            q.breakable()
+        q.text('}')
+
+class group_desc_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REQUEST
+    stats_type = 7
+
+    def __init__(self, xid=None, flags=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = group_desc_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 7)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group_desc_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+            q.breakable()
+        q.text('}')
+
+class group_features_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REPLY
+    stats_type = 8
+
+    def __init__(self, xid=None, flags=None, types=None, capabilities=None, max_groups_all=None, max_groups_select=None, max_groups_indirect=None, max_groups_ff=None, actions_all=None, actions_select=None, actions_indirect=None, actions_ff=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if types != None:
+            self.types = types
+        else:
+            self.types = 0
+        if capabilities != None:
+            self.capabilities = capabilities
+        else:
+            self.capabilities = 0
+        if max_groups_all != None:
+            self.max_groups_all = max_groups_all
+        else:
+            self.max_groups_all = 0
+        if max_groups_select != None:
+            self.max_groups_select = max_groups_select
+        else:
+            self.max_groups_select = 0
+        if max_groups_indirect != None:
+            self.max_groups_indirect = max_groups_indirect
+        else:
+            self.max_groups_indirect = 0
+        if max_groups_ff != None:
+            self.max_groups_ff = max_groups_ff
+        else:
+            self.max_groups_ff = 0
+        if actions_all != None:
+            self.actions_all = actions_all
+        else:
+            self.actions_all = 0
+        if actions_select != None:
+            self.actions_select = actions_select
+        else:
+            self.actions_select = 0
+        if actions_indirect != None:
+            self.actions_indirect = actions_indirect
+        else:
+            self.actions_indirect = 0
+        if actions_ff != None:
+            self.actions_ff = actions_ff
+        else:
+            self.actions_ff = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!L", self.types))
+        packed.append(struct.pack("!L", self.capabilities))
+        packed.append(struct.pack("!L", self.max_groups_all))
+        packed.append(struct.pack("!L", self.max_groups_select))
+        packed.append(struct.pack("!L", self.max_groups_indirect))
+        packed.append(struct.pack("!L", self.max_groups_ff))
+        packed.append(struct.pack("!L", self.actions_all))
+        packed.append(struct.pack("!L", self.actions_select))
+        packed.append(struct.pack("!L", self.actions_indirect))
+        packed.append(struct.pack("!L", self.actions_ff))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = group_features_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 8)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.types = reader.read('!L')[0]
+        obj.capabilities = reader.read('!L')[0]
+        obj.max_groups_all = reader.read('!L')[0]
+        obj.max_groups_select = reader.read('!L')[0]
+        obj.max_groups_indirect = reader.read('!L')[0]
+        obj.max_groups_ff = reader.read('!L')[0]
+        obj.actions_all = reader.read('!L')[0]
+        obj.actions_select = reader.read('!L')[0]
+        obj.actions_indirect = reader.read('!L')[0]
+        obj.actions_ff = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.types != other.types: return False
+        if self.capabilities != other.capabilities: return False
+        if self.max_groups_all != other.max_groups_all: return False
+        if self.max_groups_select != other.max_groups_select: return False
+        if self.max_groups_indirect != other.max_groups_indirect: return False
+        if self.max_groups_ff != other.max_groups_ff: return False
+        if self.actions_all != other.actions_all: return False
+        if self.actions_select != other.actions_select: return False
+        if self.actions_indirect != other.actions_indirect: return False
+        if self.actions_ff != other.actions_ff: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group_features_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("types = ");
+                q.text("%#x" % self.types)
+                q.text(","); q.breakable()
+                q.text("capabilities = ");
+                q.text("%#x" % self.capabilities)
+                q.text(","); q.breakable()
+                q.text("max_groups_all = ");
+                q.text("%#x" % self.max_groups_all)
+                q.text(","); q.breakable()
+                q.text("max_groups_select = ");
+                q.text("%#x" % self.max_groups_select)
+                q.text(","); q.breakable()
+                q.text("max_groups_indirect = ");
+                q.text("%#x" % self.max_groups_indirect)
+                q.text(","); q.breakable()
+                q.text("max_groups_ff = ");
+                q.text("%#x" % self.max_groups_ff)
+                q.text(","); q.breakable()
+                q.text("actions_all = ");
+                q.text("%#x" % self.actions_all)
+                q.text(","); q.breakable()
+                q.text("actions_select = ");
+                q.text("%#x" % self.actions_select)
+                q.text(","); q.breakable()
+                q.text("actions_indirect = ");
+                q.text("%#x" % self.actions_indirect)
+                q.text(","); q.breakable()
+                q.text("actions_ff = ");
+                q.text("%#x" % self.actions_ff)
+            q.breakable()
+        q.text('}')
+
+class group_features_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REQUEST
+    stats_type = 8
+
+    def __init__(self, xid=None, flags=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = group_features_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 8)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group_features_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+            q.breakable()
+        q.text('}')
+
+class group_mod(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_GROUP_MOD
+
+    def __init__(self, xid=None, command=None, group_type=None, group_id=None, buckets=None):
+        self.xid = xid
+        if command != None:
+            self.command = command
+        else:
+            self.command = 0
+        if group_type != None:
+            self.group_type = group_type
+        else:
+            self.group_type = 0
+        if group_id != None:
+            self.group_id = group_id
+        else:
+            self.group_id = 0
+        if buckets != None:
+            self.buckets = buckets
+        else:
+            self.buckets = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.command))
+        packed.append(struct.pack("!B", self.group_type))
+        packed.append('\x00' * 1)
+        packed.append(struct.pack("!L", self.group_id))
+        packed.append("".join([x.pack() for x in self.buckets]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = group_mod()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_GROUP_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.command = reader.read('!H')[0]
+        obj.group_type = reader.read('!B')[0]
+        reader.skip(1)
+        obj.group_id = reader.read('!L')[0]
+        obj.buckets = common.unpack_list_bucket(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.command != other.command: return False
+        if self.group_type != other.group_type: return False
+        if self.group_id != other.group_id: return False
+        if self.buckets != other.buckets: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group_mod {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("command = ");
+                q.text("%#x" % self.command)
+                q.text(","); q.breakable()
+                q.text("group_type = ");
+                q.text("%#x" % self.group_type)
+                q.text(","); q.breakable()
+                q.text("group_id = ");
+                q.text("%#x" % self.group_id)
+                q.text(","); q.breakable()
+                q.text("buckets = ");
+                q.pp(self.buckets)
+            q.breakable()
+        q.text('}')
+
+class group_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REPLY
+    stats_type = 6
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.entries]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = group_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 6)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.entries = common.unpack_list_group_stats_entry(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.entries != other.entries: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("entries = ");
+                q.pp(self.entries)
+            q.breakable()
+        q.text('}')
+
+class group_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REQUEST
+    stats_type = 6
+
+    def __init__(self, xid=None, flags=None, group_id=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if group_id != None:
+            self.group_id = group_id
+        else:
+            self.group_id = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!L", self.group_id))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = group_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 6)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.group_id = reader.read('!L')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.group_id != other.group_id: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("group_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("group_id = ");
+                q.text("%#x" % self.group_id)
+            q.breakable()
+        q.text('}')
+
+class hello(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_HELLO
+
+    def __init__(self, xid=None, elements=None):
+        self.xid = xid
+        if elements != None:
+            self.elements = elements
+        else:
+            self.elements = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append("".join([x.pack() for x in self.elements]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = hello()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_HELLO)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.elements = common.unpack_list_hello_elem(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.elements != other.elements: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("hello {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("elements = ");
+                q.pp(self.elements)
+            q.breakable()
+        q.text('}')
+
+class meter_config_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REPLY
+    stats_type = 10
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.entries]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = meter_config_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 10)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.entries = meter_band.unpack_list(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.entries != other.entries: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("meter_config_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("entries = ");
+                q.pp(self.entries)
+            q.breakable()
+        q.text('}')
+
+class meter_config_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REQUEST
+    stats_type = 10
+
+    def __init__(self, xid=None, flags=None, meter_id=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if meter_id != None:
+            self.meter_id = meter_id
+        else:
+            self.meter_id = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!L", self.meter_id))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = meter_config_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 10)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.meter_id = reader.read('!L')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.meter_id != other.meter_id: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("meter_config_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("meter_id = ");
+                q.text("%#x" % self.meter_id)
+            q.breakable()
+        q.text('}')
+
+class meter_features_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REPLY
+    stats_type = 11
+
+    def __init__(self, xid=None, flags=None, features=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if features != None:
+            self.features = features
+        else:
+            self.features = common.meter_features()
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(self.features.pack())
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = meter_features_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 11)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.features = common.meter_features.unpack(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.features != other.features: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("meter_features_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("features = ");
+                q.pp(self.features)
+            q.breakable()
+        q.text('}')
+
+class meter_features_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REQUEST
+    stats_type = 11
+
+    def __init__(self, xid=None, flags=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = meter_features_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 11)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("meter_features_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+            q.breakable()
+        q.text('}')
+
+class meter_mod(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_METER_MOD
+
+    def __init__(self, xid=None, command=None, flags=None, meter_id=None, meters=None):
+        self.xid = xid
+        if command != None:
+            self.command = command
+        else:
+            self.command = 0
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if meter_id != None:
+            self.meter_id = meter_id
+        else:
+            self.meter_id = 0
+        if meters != None:
+            self.meters = meters
+        else:
+            self.meters = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.command))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append(struct.pack("!L", self.meter_id))
+        packed.append("".join([x.pack() for x in self.meters]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = meter_mod()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_METER_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.command = reader.read('!H')[0]
+        obj.flags = reader.read('!H')[0]
+        obj.meter_id = reader.read('!L')[0]
+        obj.meters = meter_band.unpack_list(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.command != other.command: return False
+        if self.flags != other.flags: return False
+        if self.meter_id != other.meter_id: return False
+        if self.meters != other.meters: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("meter_mod {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("command = ");
+                q.text("%#x" % self.command)
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("meter_id = ");
+                q.text("%#x" % self.meter_id)
+                q.text(","); q.breakable()
+                q.text("meters = ");
+                q.pp(self.meters)
+            q.breakable()
+        q.text('}')
+
+class meter_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REPLY
+    stats_type = 9
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.entries]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = meter_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 9)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.entries = common.unpack_list_meter_stats(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.entries != other.entries: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("meter_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("entries = ");
+                q.pp(self.entries)
+            q.breakable()
+        q.text('}')
+
+class meter_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REQUEST
+    stats_type = 9
+
+    def __init__(self, xid=None, flags=None, meter_id=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if meter_id != None:
+            self.meter_id = meter_id
+        else:
+            self.meter_id = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!L", self.meter_id))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = meter_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 9)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.meter_id = reader.read('!L')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.meter_id != other.meter_id: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("meter_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("meter_id = ");
+                q.text("%#x" % self.meter_id)
+            q.breakable()
+        q.text('}')
+
+class packet_in(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_PACKET_IN
+
+    def __init__(self, xid=None, buffer_id=None, total_len=None, reason=None, table_id=None, cookie=None, match=None, data=None):
+        self.xid = xid
+        if buffer_id != None:
+            self.buffer_id = buffer_id
+        else:
+            self.buffer_id = 0
+        if total_len != None:
+            self.total_len = total_len
+        else:
+            self.total_len = 0
+        if reason != None:
+            self.reason = reason
+        else:
+            self.reason = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if cookie != None:
+            self.cookie = cookie
+        else:
+            self.cookie = 0
+        if match != None:
+            self.match = match
+        else:
+            self.match = common.match()
+        if data != None:
+            self.data = data
+        else:
+            self.data = ""
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.buffer_id))
+        packed.append(struct.pack("!H", self.total_len))
+        packed.append(struct.pack("!B", self.reason))
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append(struct.pack("!Q", self.cookie))
+        packed.append(self.match.pack())
+        packed.append('\x00' * 2)
+        packed.append(self.data)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = packet_in()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_PACKET_IN)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.total_len = reader.read('!H')[0]
+        obj.reason = reader.read('!B')[0]
+        obj.table_id = reader.read('!B')[0]
+        obj.cookie = reader.read('!Q')[0]
+        obj.match = common.match.unpack(reader)
+        reader.skip(2)
+        obj.data = str(reader.read_all())
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.buffer_id != other.buffer_id: return False
+        if self.total_len != other.total_len: return False
+        if self.reason != other.reason: return False
+        if self.table_id != other.table_id: return False
+        if self.cookie != other.cookie: return False
+        if self.match != other.match: return False
+        if self.data != other.data: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("packet_in {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("buffer_id = ");
+                q.text("%#x" % self.buffer_id)
+                q.text(","); q.breakable()
+                q.text("total_len = ");
+                q.text("%#x" % self.total_len)
+                q.text(","); q.breakable()
+                q.text("reason = ");
+                q.text("%#x" % self.reason)
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("cookie = ");
+                q.text("%#x" % self.cookie)
+                q.text(","); q.breakable()
+                q.text("match = ");
+                q.pp(self.match)
+                q.text(","); q.breakable()
+                q.text("data = ");
+                q.pp(self.data)
+            q.breakable()
+        q.text('}')
+
+class packet_out(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_PACKET_OUT
+
+    def __init__(self, xid=None, buffer_id=None, in_port=None, actions=None, data=None):
+        self.xid = xid
+        if buffer_id != None:
+            self.buffer_id = buffer_id
+        else:
+            self.buffer_id = 0
+        if in_port != None:
+            self.in_port = in_port
+        else:
+            self.in_port = 0
+        if actions != None:
+            self.actions = actions
+        else:
+            self.actions = []
+        if data != None:
+            self.data = data
+        else:
+            self.data = ""
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.buffer_id))
+        packed.append(struct.pack("!L", self.in_port))
+        packed.append(struct.pack("!H", 0)) # placeholder for actions_len at index 6
+        packed.append('\x00' * 6)
+        packed.append("".join([x.pack() for x in self.actions]))
+        packed[6] = struct.pack("!H", len(packed[-1]))
+        packed.append(self.data)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = packet_out()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_PACKET_OUT)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.buffer_id = reader.read('!L')[0]
+        obj.in_port = reader.read('!L')[0]
+        _actions_len = reader.read('!H')[0]
+        reader.skip(6)
+        obj.actions = action.unpack_list(reader.slice(_actions_len))
+        obj.data = str(reader.read_all())
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.buffer_id != other.buffer_id: return False
+        if self.in_port != other.in_port: return False
+        if self.actions != other.actions: return False
+        if self.data != other.data: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("packet_out {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("buffer_id = ");
+                q.text("%#x" % self.buffer_id)
+                q.text(","); q.breakable()
+                q.text("in_port = ");
+                q.text(util.pretty_port(self.in_port))
+                q.text(","); q.breakable()
+                q.text("actions = ");
+                q.pp(self.actions)
+                q.text(","); q.breakable()
+                q.text("data = ");
+                q.pp(self.data)
+            q.breakable()
+        q.text('}')
+
+class port_desc_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REPLY
+    stats_type = 13
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.entries]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = port_desc_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 13)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.entries = loxi.generic_util.unpack_list(reader, common.port_desc.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.entries != other.entries: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("port_desc_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("entries = ");
+                q.pp(self.entries)
+            q.breakable()
+        q.text('}')
+
+class port_desc_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REQUEST
+    stats_type = 13
+
+    def __init__(self, xid=None, flags=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = port_desc_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 13)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("port_desc_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+            q.breakable()
+        q.text('}')
+
+class port_mod(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_PORT_MOD
+
+    def __init__(self, xid=None, port_no=None, hw_addr=None, config=None, mask=None, advertise=None):
+        self.xid = xid
+        if port_no != None:
+            self.port_no = port_no
+        else:
+            self.port_no = 0
+        if hw_addr != None:
+            self.hw_addr = hw_addr
+        else:
+            self.hw_addr = [0,0,0,0,0,0]
+        if config != None:
+            self.config = config
+        else:
+            self.config = 0
+        if mask != None:
+            self.mask = mask
+        else:
+            self.mask = 0
+        if advertise != None:
+            self.advertise = advertise
+        else:
+            self.advertise = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.port_no))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!6B", *self.hw_addr))
+        packed.append('\x00' * 2)
+        packed.append(struct.pack("!L", self.config))
+        packed.append(struct.pack("!L", self.mask))
+        packed.append(struct.pack("!L", self.advertise))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = port_mod()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_PORT_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.port_no = reader.read('!L')[0]
+        reader.skip(4)
+        obj.hw_addr = list(reader.read('!6B'))
+        reader.skip(2)
+        obj.config = reader.read('!L')[0]
+        obj.mask = reader.read('!L')[0]
+        obj.advertise = reader.read('!L')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.port_no != other.port_no: return False
+        if self.hw_addr != other.hw_addr: return False
+        if self.config != other.config: return False
+        if self.mask != other.mask: return False
+        if self.advertise != other.advertise: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("port_mod {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("port_no = ");
+                q.text(util.pretty_port(self.port_no))
+                q.text(","); q.breakable()
+                q.text("hw_addr = ");
+                q.text(util.pretty_mac(self.hw_addr))
+                q.text(","); q.breakable()
+                q.text("config = ");
+                q.text("%#x" % self.config)
+                q.text(","); q.breakable()
+                q.text("mask = ");
+                q.text("%#x" % self.mask)
+                q.text(","); q.breakable()
+                q.text("advertise = ");
+                q.text("%#x" % self.advertise)
+            q.breakable()
+        q.text('}')
+
+class port_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REPLY
+    stats_type = 4
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.entries]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = port_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 4)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.entries = loxi.generic_util.unpack_list(reader, common.port_stats_entry.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.entries != other.entries: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("port_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("entries = ");
+                q.pp(self.entries)
+            q.breakable()
+        q.text('}')
+
+class port_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REQUEST
+    stats_type = 4
+
+    def __init__(self, xid=None, flags=None, port_no=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if port_no != None:
+            self.port_no = port_no
+        else:
+            self.port_no = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!L", self.port_no))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = port_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 4)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.port_no = reader.read('!L')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.port_no != other.port_no: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("port_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("port_no = ");
+                q.text(util.pretty_port(self.port_no))
+            q.breakable()
+        q.text('}')
+
+class port_status(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_PORT_STATUS
+
+    def __init__(self, xid=None, reason=None, desc=None):
+        self.xid = xid
+        if reason != None:
+            self.reason = reason
+        else:
+            self.reason = 0
+        if desc != None:
+            self.desc = desc
+        else:
+            self.desc = common.port_desc()
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!B", self.reason))
+        packed.append('\x00' * 7)
+        packed.append(self.desc.pack())
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = port_status()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_PORT_STATUS)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.reason = reader.read('!B')[0]
+        reader.skip(7)
+        obj.desc = common.port_desc.unpack(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.reason != other.reason: return False
+        if self.desc != other.desc: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("port_status {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("reason = ");
+                q.text("%#x" % self.reason)
+                q.text(","); q.breakable()
+                q.text("desc = ");
+                q.pp(self.desc)
+            q.breakable()
+        q.text('}')
+
+class queue_get_config_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_QUEUE_GET_CONFIG_REPLY
+
+    def __init__(self, xid=None, port=None, queues=None):
+        self.xid = xid
+        if port != None:
+            self.port = port
+        else:
+            self.port = 0
+        if queues != None:
+            self.queues = queues
+        else:
+            self.queues = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.port))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.queues]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = queue_get_config_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_QUEUE_GET_CONFIG_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.port = reader.read('!L')[0]
+        reader.skip(4)
+        obj.queues = common.unpack_list_packet_queue(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.port != other.port: return False
+        if self.queues != other.queues: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("queue_get_config_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("port = ");
+                q.text(util.pretty_port(self.port))
+                q.text(","); q.breakable()
+                q.text("queues = ");
+                q.pp(self.queues)
+            q.breakable()
+        q.text('}')
+
+class queue_get_config_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_QUEUE_GET_CONFIG_REQUEST
+
+    def __init__(self, xid=None, port=None):
+        self.xid = xid
+        if port != None:
+            self.port = port
+        else:
+            self.port = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.port))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = queue_get_config_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_QUEUE_GET_CONFIG_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.port = reader.read('!L')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.port != other.port: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("queue_get_config_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("port = ");
+                q.text(util.pretty_port(self.port))
+            q.breakable()
+        q.text('}')
+
+class queue_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REPLY
+    stats_type = 5
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.entries]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = queue_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 5)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.entries = loxi.generic_util.unpack_list(reader, common.queue_stats_entry.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.entries != other.entries: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("queue_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("entries = ");
+                q.pp(self.entries)
+            q.breakable()
+        q.text('}')
+
+class queue_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REQUEST
+    stats_type = 5
+
+    def __init__(self, xid=None, flags=None, port_no=None, queue_id=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if port_no != None:
+            self.port_no = port_no
+        else:
+            self.port_no = 0
+        if queue_id != None:
+            self.queue_id = queue_id
+        else:
+            self.queue_id = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!L", self.port_no))
+        packed.append(struct.pack("!L", self.queue_id))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = queue_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 5)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.port_no = reader.read('!L')[0]
+        obj.queue_id = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.port_no != other.port_no: return False
+        if self.queue_id != other.queue_id: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("queue_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("port_no = ");
+                q.text(util.pretty_port(self.port_no))
+                q.text(","); q.breakable()
+                q.text("queue_id = ");
+                q.text("%#x" % self.queue_id)
+            q.breakable()
+        q.text('}')
+
+class role_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_ROLE_REPLY
+
+    def __init__(self, xid=None, data=None):
+        self.xid = xid
+        if data != None:
+            self.data = data
+        else:
+            self.data = ""
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(self.data)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = role_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_ROLE_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.data = str(reader.read_all())
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.data != other.data: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("role_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("data = ");
+                q.pp(self.data)
+            q.breakable()
+        q.text('}')
+
+class role_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_ROLE_REQUEST
+
+    def __init__(self, xid=None, role=None, generation_id=None):
+        self.xid = xid
+        if role != None:
+            self.role = role
+        else:
+            self.role = 0
+        if generation_id != None:
+            self.generation_id = generation_id
+        else:
+            self.generation_id = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!L", self.role))
+        packed.append('\x00' * 4)
+        packed.append(struct.pack("!Q", self.generation_id))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = role_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_ROLE_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.role = reader.read('!L')[0]
+        reader.skip(4)
+        obj.generation_id = reader.read('!Q')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.role != other.role: return False
+        if self.generation_id != other.generation_id: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("role_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("role = ");
+                q.text("%#x" % self.role)
+                q.text(","); q.breakable()
+                q.text("generation_id = ");
+                q.text("%#x" % self.generation_id)
+            q.breakable()
+        q.text('}')
+
+class set_config(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_SET_CONFIG
+
+    def __init__(self, xid=None, flags=None, miss_send_len=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if miss_send_len != None:
+            self.miss_send_len = miss_send_len
+        else:
+            self.miss_send_len = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append(struct.pack("!H", self.miss_send_len))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = set_config()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_SET_CONFIG)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.flags = reader.read('!H')[0]
+        obj.miss_send_len = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.miss_send_len != other.miss_send_len: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("set_config {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("miss_send_len = ");
+                q.text("%#x" % self.miss_send_len)
+            q.breakable()
+        q.text('}')
+
+class table_features_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REPLY
+    stats_type = 12
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.entries]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = table_features_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 12)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.entries = loxi.unimplemented('unpack list of_list_table_features_t')
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.entries != other.entries: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_features_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("entries = ");
+                q.pp(self.entries)
+            q.breakable()
+        q.text('}')
+
+class table_features_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REQUEST
+    stats_type = 12
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.entries]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = table_features_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 12)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.entries = loxi.unimplemented('unpack list of_list_table_features_t')
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.entries != other.entries: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_features_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("entries = ");
+                q.pp(self.entries)
+            q.breakable()
+        q.text('}')
+
+class table_mod(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_TABLE_MOD
+
+    def __init__(self, xid=None, table_id=None, config=None):
+        self.xid = xid
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if config != None:
+            self.config = config
+        else:
+            self.config = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!B", self.table_id))
+        packed.append('\x00' * 3)
+        packed.append(struct.pack("!L", self.config))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = table_mod()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_TABLE_MOD)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        obj.table_id = reader.read('!B')[0]
+        reader.skip(3)
+        obj.config = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.table_id != other.table_id: return False
+        if self.config != other.config: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_mod {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("config = ");
+                q.text("%#x" % self.config)
+            q.breakable()
+        q.text('}')
+
+class table_stats_reply(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REPLY
+    stats_type = 3
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        packed.append("".join([x.pack() for x in self.entries]))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = table_stats_reply()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REPLY)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 3)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        obj.entries = loxi.generic_util.unpack_list(reader, common.table_stats_entry.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        if self.entries != other.entries: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_stats_reply {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+                q.text(","); q.breakable()
+                q.text("entries = ");
+                q.pp(self.entries)
+            q.breakable()
+        q.text('}')
+
+class table_stats_request(Message):
+    version = const.OFP_VERSION
+    type = const.OFPT_MULTIPART_REQUEST
+    stats_type = 3
+
+    def __init__(self, xid=None, flags=None):
+        self.xid = xid
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.version))
+        packed.append(struct.pack("!B", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 2
+        packed.append(struct.pack("!L", self.xid))
+        packed.append(struct.pack("!H", self.stats_type))
+        packed.append(struct.pack("!H", self.flags))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        if len(buf) < 8: raise loxi.ProtocolError("buffer too short to contain an OpenFlow message")
+        obj = table_stats_request()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _version = reader.read('!B')[0]
+        assert(_version == const.OFP_VERSION)
+        _type = reader.read('!B')[0]
+        assert(_type == const.OFPT_MULTIPART_REQUEST)
+        _length = reader.read('!H')[0]
+        obj.xid = reader.read('!L')[0]
+        _stats_type = reader.read('!H')[0]
+        assert(_stats_type == 3)
+        obj.flags = reader.read('!H')[0]
+        reader.skip(4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.version != other.version: return False
+        if self.type != other.type: return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def __str__(self):
+        return self.show()
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("table_stats_request {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("xid = ");
+                if self.xid != None:
+                    q.text("%#x" % self.xid)
+                else:
+                    q.text('None')
+                q.text(","); q.breakable()
+                q.text("flags = ");
+                q.text("%#x" % self.flags)
+            q.breakable()
+        q.text('}')
+
+
+def parse_header(buf):
+    if len(buf) < 8:
+        raise loxi.ProtocolError("too short to be an OpenFlow message")
+    return struct.unpack_from("!BBHL", buf)
+
+def parse_message(buf):
+    msg_ver, msg_type, msg_len, msg_xid = parse_header(buf)
+    if msg_ver != const.OFP_VERSION and msg_type != ofp.OFPT_HELLO:
+        raise loxi.ProtocolError("wrong OpenFlow version")
+    if len(buf) != msg_len:
+        raise loxi.ProtocolError("incorrect message size")
+    if msg_type in parsers:
+        return parsers[msg_type](buf)
+    else:
+        raise loxi.ProtocolError("unexpected message type")
+
+def parse_flow_mod(buf):
+    if len(buf) < 56 + 2:
+        raise loxi.ProtocolError("message too short")
+    cmd, = struct.unpack_from("!H", buf, 56)
+    if cmd in flow_mod_parsers:
+        return flow_mod_parsers[cmd](buf)
+    else:
+        raise loxi.ProtocolError("unexpected flow mod cmd %u" % cmd)
+
+def parse_multipart_reply(buf):
+    if len(buf) < 8 + 2:
+        raise loxi.ProtocolError("message too short")
+    multipart_type, = struct.unpack_from("!H", buf, 8)
+    if multipart_type in multipart_reply_parsers:
+        return multipart_reply_parsers[multipart_type](buf)
+    else:
+        raise loxi.ProtocolError("unexpected multipart type %u" % multipart_type)
+
+def parse_multipart_request(buf):
+    if len(buf) < 8 + 2:
+        raise loxi.ProtocolError("message too short")
+    multipart_type, = struct.unpack_from("!H", buf, 8)
+    if multipart_type in multipart_request_parsers:
+        return multipart_request_parsers[multipart_type](buf)
+    else:
+        raise loxi.ProtocolError("unexpected multipart type %u" % multipart_type)
+
+def parse_experimenter(buf):
+    if len(buf) < 16:
+        raise loxi.ProtocolError("experimenter message too short")
+
+    experimenter, = struct.unpack_from("!L", buf, 8)
+    if experimenter == 0x005c16c7: # Big Switch Networks
+        subtype, = struct.unpack_from("!L", buf, 12)
+    elif experimenter == 0x00002320: # Nicira
+        subtype, = struct.unpack_from("!L", buf, 12)
+    else:
+        raise loxi.ProtocolError("unexpected experimenter id %#x" % experimenter)
+
+    if subtype in experimenter_parsers[experimenter]:
+        return experimenter_parsers[experimenter][subtype](buf)
+    else:
+        raise loxi.ProtocolError("unexpected experimenter %#x subtype %#x" % (experimenter, subtype))
+
+parsers = {
+    const.OFPT_BARRIER_REPLY : barrier_reply.unpack,
+    const.OFPT_BARRIER_REQUEST : barrier_request.unpack,
+    const.OFPT_ECHO_REPLY : echo_reply.unpack,
+    const.OFPT_ECHO_REQUEST : echo_request.unpack,
+    const.OFPT_ERROR : error_msg.unpack,
+    const.OFPT_EXPERIMENTER : parse_experimenter,
+    const.OFPT_FEATURES_REPLY : features_reply.unpack,
+    const.OFPT_FEATURES_REQUEST : features_request.unpack,
+    const.OFPT_FLOW_MOD : parse_flow_mod,
+    const.OFPT_FLOW_REMOVED : flow_removed.unpack,
+    const.OFPT_GET_ASYNC_REPLY : async_get_reply.unpack,
+    const.OFPT_GET_ASYNC_REQUEST : async_get_request.unpack,
+    const.OFPT_GET_CONFIG_REPLY : get_config_reply.unpack,
+    const.OFPT_GET_CONFIG_REQUEST : get_config_request.unpack,
+    const.OFPT_GROUP_MOD : group_mod.unpack,
+    const.OFPT_HELLO : hello.unpack,
+    const.OFPT_METER_MOD : meter_mod.unpack,
+    const.OFPT_MULTIPART_REPLY : parse_multipart_reply,
+    const.OFPT_MULTIPART_REQUEST : parse_multipart_request,
+    const.OFPT_PACKET_IN : packet_in.unpack,
+    const.OFPT_PACKET_OUT : packet_out.unpack,
+    const.OFPT_PORT_MOD : port_mod.unpack,
+    const.OFPT_PORT_STATUS : port_status.unpack,
+    const.OFPT_QUEUE_GET_CONFIG_REPLY : queue_get_config_reply.unpack,
+    const.OFPT_QUEUE_GET_CONFIG_REQUEST : queue_get_config_request.unpack,
+    const.OFPT_ROLE_REPLY : role_reply.unpack,
+    const.OFPT_ROLE_REQUEST : role_request.unpack,
+    const.OFPT_SET_ASYNC : async_set.unpack,
+    const.OFPT_SET_CONFIG : set_config.unpack,
+    const.OFPT_TABLE_MOD : table_mod.unpack,
+}
+
+flow_mod_parsers = {
+    const.OFPFC_ADD : flow_add.unpack,
+    const.OFPFC_MODIFY : flow_modify.unpack,
+    const.OFPFC_MODIFY_STRICT : flow_modify_strict.unpack,
+    const.OFPFC_DELETE : flow_delete.unpack,
+    const.OFPFC_DELETE_STRICT : flow_delete_strict.unpack,
+}
+
+
+
+experimenter_parsers = {
+}
diff --git a/src/python/loxi/of13/oxm.py b/src/python/loxi/of13/oxm.py
new file mode 100644
index 0000000..d3bc046
--- /dev/null
+++ b/src/python/loxi/of13/oxm.py
@@ -0,0 +1,3990 @@
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+
+# Automatically generated by LOXI from template oxm.py
+# Do not modify
+
+import struct
+import const
+import util
+import loxi.generic_util
+import loxi
+
+def unpack_list(reader):
+    def deserializer(reader):
+        type_len, = reader.peek('!L')
+        if type_len in parsers:
+            return parsers[type_len](reader)
+        else:
+            raise loxi.ProtocolError("unknown OXM cls=%#x type=%#x masked=%d len=%d (%#x)" % \
+                ((type_len >> 16) & 0xffff, (type_len >> 9) & 0x7f, (type_len >> 8) & 1, type_len & 0xff, type_len))
+    return loxi.generic_util.unpack_list(reader, deserializer)
+
+class OXM(object):
+    type_len = None # override in subclass
+    pass
+
+class arp_op(OXM):
+    type_len = 0x80002a02
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = arp_op()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002a02)
+        obj.value = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("arp_op {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class arp_op_masked(OXM):
+    type_len = 0x80002b04
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        packed.append(struct.pack("!H", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = arp_op_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002b04)
+        obj.value = reader.read('!H')[0]
+        obj.value_mask = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("arp_op_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class arp_sha(OXM):
+    type_len = 0x80003006
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = [0,0,0,0,0,0]
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!6B", *self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = arp_sha()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003006)
+        obj.value = list(reader.read('!6B'))
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("arp_sha {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_mac(self.value))
+            q.breakable()
+        q.text('}')
+
+class arp_sha_masked(OXM):
+    type_len = 0x8000310c
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = [0,0,0,0,0,0]
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = [0,0,0,0,0,0]
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!6B", *self.value))
+        packed.append(struct.pack("!6B", *self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = arp_sha_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x8000310c)
+        obj.value = list(reader.read('!6B'))
+        obj.value_mask = list(reader.read('!6B'))
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("arp_sha_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_mac(self.value))
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text(util.pretty_mac(self.value_mask))
+            q.breakable()
+        q.text('}')
+
+class arp_spa(OXM):
+    type_len = 0x80002c04
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = arp_spa()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002c04)
+        obj.value = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("arp_spa {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class arp_spa_masked(OXM):
+    type_len = 0x80002d08
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        packed.append(struct.pack("!L", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = arp_spa_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002d08)
+        obj.value = reader.read('!L')[0]
+        obj.value_mask = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("arp_spa_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class arp_tha(OXM):
+    type_len = 0x80003206
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = [0,0,0,0,0,0]
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!6B", *self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = arp_tha()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003206)
+        obj.value = list(reader.read('!6B'))
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("arp_tha {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_mac(self.value))
+            q.breakable()
+        q.text('}')
+
+class arp_tha_masked(OXM):
+    type_len = 0x8000330c
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = [0,0,0,0,0,0]
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = [0,0,0,0,0,0]
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!6B", *self.value))
+        packed.append(struct.pack("!6B", *self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = arp_tha_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x8000330c)
+        obj.value = list(reader.read('!6B'))
+        obj.value_mask = list(reader.read('!6B'))
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("arp_tha_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_mac(self.value))
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text(util.pretty_mac(self.value_mask))
+            q.breakable()
+        q.text('}')
+
+class arp_tpa(OXM):
+    type_len = 0x80002e04
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = arp_tpa()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002e04)
+        obj.value = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("arp_tpa {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class arp_tpa_masked(OXM):
+    type_len = 0x80002f08
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        packed.append(struct.pack("!L", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = arp_tpa_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002f08)
+        obj.value = reader.read('!L')[0]
+        obj.value_mask = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("arp_tpa_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class eth_dst(OXM):
+    type_len = 0x80000606
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = [0,0,0,0,0,0]
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!6B", *self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = eth_dst()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000606)
+        obj.value = list(reader.read('!6B'))
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("eth_dst {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_mac(self.value))
+            q.breakable()
+        q.text('}')
+
+class eth_dst_masked(OXM):
+    type_len = 0x8000070c
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = [0,0,0,0,0,0]
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = [0,0,0,0,0,0]
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!6B", *self.value))
+        packed.append(struct.pack("!6B", *self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = eth_dst_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x8000070c)
+        obj.value = list(reader.read('!6B'))
+        obj.value_mask = list(reader.read('!6B'))
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("eth_dst_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_mac(self.value))
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text(util.pretty_mac(self.value_mask))
+            q.breakable()
+        q.text('}')
+
+class eth_src(OXM):
+    type_len = 0x80000806
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = [0,0,0,0,0,0]
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!6B", *self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = eth_src()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000806)
+        obj.value = list(reader.read('!6B'))
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("eth_src {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_mac(self.value))
+            q.breakable()
+        q.text('}')
+
+class eth_src_masked(OXM):
+    type_len = 0x8000090c
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = [0,0,0,0,0,0]
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = [0,0,0,0,0,0]
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!6B", *self.value))
+        packed.append(struct.pack("!6B", *self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = eth_src_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x8000090c)
+        obj.value = list(reader.read('!6B'))
+        obj.value_mask = list(reader.read('!6B'))
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("eth_src_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_mac(self.value))
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text(util.pretty_mac(self.value_mask))
+            q.breakable()
+        q.text('}')
+
+class eth_type(OXM):
+    type_len = 0x80000a02
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = eth_type()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000a02)
+        obj.value = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("eth_type {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class eth_type_masked(OXM):
+    type_len = 0x80000b04
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        packed.append(struct.pack("!H", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = eth_type_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000b04)
+        obj.value = reader.read('!H')[0]
+        obj.value_mask = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("eth_type_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class icmpv4_code(OXM):
+    type_len = 0x80002801
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = icmpv4_code()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002801)
+        obj.value = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("icmpv4_code {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class icmpv4_code_masked(OXM):
+    type_len = 0x80002902
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        packed.append(struct.pack("!B", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = icmpv4_code_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002902)
+        obj.value = reader.read('!B')[0]
+        obj.value_mask = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("icmpv4_code_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class icmpv4_type(OXM):
+    type_len = 0x80002601
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = icmpv4_type()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002601)
+        obj.value = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("icmpv4_type {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class icmpv4_type_masked(OXM):
+    type_len = 0x80002702
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        packed.append(struct.pack("!B", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = icmpv4_type_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002702)
+        obj.value = reader.read('!B')[0]
+        obj.value_mask = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("icmpv4_type_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class icmpv6_code(OXM):
+    type_len = 0x80003c01
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = icmpv6_code()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003c01)
+        obj.value = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("icmpv6_code {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class icmpv6_code_masked(OXM):
+    type_len = 0x80003d02
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        packed.append(struct.pack("!B", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = icmpv6_code_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003d02)
+        obj.value = reader.read('!B')[0]
+        obj.value_mask = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("icmpv6_code_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class icmpv6_type(OXM):
+    type_len = 0x80003a01
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = icmpv6_type()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003a01)
+        obj.value = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("icmpv6_type {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class icmpv6_type_masked(OXM):
+    type_len = 0x80003b02
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        packed.append(struct.pack("!B", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = icmpv6_type_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003b02)
+        obj.value = reader.read('!B')[0]
+        obj.value_mask = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("icmpv6_type_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class in_phy_port(OXM):
+    type_len = 0x80000204
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = in_phy_port()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000204)
+        obj.value = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("in_phy_port {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_port(self.value))
+            q.breakable()
+        q.text('}')
+
+class in_phy_port_masked(OXM):
+    type_len = 0x80000308
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        packed.append(struct.pack("!L", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = in_phy_port_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000308)
+        obj.value = reader.read('!L')[0]
+        obj.value_mask = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("in_phy_port_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_port(self.value))
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text(util.pretty_port(self.value_mask))
+            q.breakable()
+        q.text('}')
+
+class in_port(OXM):
+    type_len = 0x80000004
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = in_port()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000004)
+        obj.value = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("in_port {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_port(self.value))
+            q.breakable()
+        q.text('}')
+
+class in_port_masked(OXM):
+    type_len = 0x80000108
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        packed.append(struct.pack("!L", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = in_port_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000108)
+        obj.value = reader.read('!L')[0]
+        obj.value_mask = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("in_port_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_port(self.value))
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text(util.pretty_port(self.value_mask))
+            q.breakable()
+        q.text('}')
+
+class ip_dscp(OXM):
+    type_len = 0x80001001
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ip_dscp()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001001)
+        obj.value = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ip_dscp {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class ip_dscp_masked(OXM):
+    type_len = 0x80001102
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        packed.append(struct.pack("!B", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ip_dscp_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001102)
+        obj.value = reader.read('!B')[0]
+        obj.value_mask = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ip_dscp_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class ip_ecn(OXM):
+    type_len = 0x80001201
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ip_ecn()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001201)
+        obj.value = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ip_ecn {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class ip_ecn_masked(OXM):
+    type_len = 0x80001302
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        packed.append(struct.pack("!B", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ip_ecn_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001302)
+        obj.value = reader.read('!B')[0]
+        obj.value_mask = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ip_ecn_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class ip_proto(OXM):
+    type_len = 0x80001401
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ip_proto()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001401)
+        obj.value = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ip_proto {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class ip_proto_masked(OXM):
+    type_len = 0x80001502
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        packed.append(struct.pack("!B", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ip_proto_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001502)
+        obj.value = reader.read('!B')[0]
+        obj.value_mask = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ip_proto_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class ipv4_dst(OXM):
+    type_len = 0x80001804
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv4_dst()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001804)
+        obj.value = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv4_dst {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class ipv4_dst_masked(OXM):
+    type_len = 0x80001908
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        packed.append(struct.pack("!L", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv4_dst_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001908)
+        obj.value = reader.read('!L')[0]
+        obj.value_mask = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv4_dst_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class ipv4_src(OXM):
+    type_len = 0x80001604
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv4_src()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001604)
+        obj.value = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv4_src {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class ipv4_src_masked(OXM):
+    type_len = 0x80001708
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        packed.append(struct.pack("!L", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv4_src_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001708)
+        obj.value = reader.read('!L')[0]
+        obj.value_mask = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv4_src_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class ipv6_dst(OXM):
+    type_len = 0x80003610
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!16s", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv6_dst()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003610)
+        obj.value = reader.read('!16s')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv6_dst {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.pp(self.value)
+            q.breakable()
+        q.text('}')
+
+class ipv6_dst_masked(OXM):
+    type_len = 0x80003720
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!16s", self.value))
+        packed.append(struct.pack("!16s", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv6_dst_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003720)
+        obj.value = reader.read('!16s')[0]
+        obj.value_mask = reader.read('!16s')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv6_dst_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.pp(self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.pp(self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class ipv6_flabel(OXM):
+    type_len = 0x80003804
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv6_flabel()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003804)
+        obj.value = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv6_flabel {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class ipv6_flabel_masked(OXM):
+    type_len = 0x80003908
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        packed.append(struct.pack("!L", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv6_flabel_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003908)
+        obj.value = reader.read('!L')[0]
+        obj.value_mask = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv6_flabel_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class ipv6_nd_sll(OXM):
+    type_len = 0x80004006
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = [0,0,0,0,0,0]
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!6B", *self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv6_nd_sll()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80004006)
+        obj.value = list(reader.read('!6B'))
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv6_nd_sll {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_mac(self.value))
+            q.breakable()
+        q.text('}')
+
+class ipv6_nd_sll_masked(OXM):
+    type_len = 0x8000410c
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = [0,0,0,0,0,0]
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = [0,0,0,0,0,0]
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!6B", *self.value))
+        packed.append(struct.pack("!6B", *self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv6_nd_sll_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x8000410c)
+        obj.value = list(reader.read('!6B'))
+        obj.value_mask = list(reader.read('!6B'))
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv6_nd_sll_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_mac(self.value))
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text(util.pretty_mac(self.value_mask))
+            q.breakable()
+        q.text('}')
+
+class ipv6_nd_target(OXM):
+    type_len = 0x80003e10
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!16s", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv6_nd_target()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003e10)
+        obj.value = reader.read('!16s')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv6_nd_target {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.pp(self.value)
+            q.breakable()
+        q.text('}')
+
+class ipv6_nd_target_masked(OXM):
+    type_len = 0x80003f20
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!16s", self.value))
+        packed.append(struct.pack("!16s", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv6_nd_target_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003f20)
+        obj.value = reader.read('!16s')[0]
+        obj.value_mask = reader.read('!16s')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv6_nd_target_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.pp(self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.pp(self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class ipv6_nd_tll(OXM):
+    type_len = 0x80004206
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = [0,0,0,0,0,0]
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!6B", *self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv6_nd_tll()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80004206)
+        obj.value = list(reader.read('!6B'))
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv6_nd_tll {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_mac(self.value))
+            q.breakable()
+        q.text('}')
+
+class ipv6_nd_tll_masked(OXM):
+    type_len = 0x8000430c
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = [0,0,0,0,0,0]
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = [0,0,0,0,0,0]
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!6B", *self.value))
+        packed.append(struct.pack("!6B", *self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv6_nd_tll_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x8000430c)
+        obj.value = list(reader.read('!6B'))
+        obj.value_mask = list(reader.read('!6B'))
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv6_nd_tll_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_mac(self.value))
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text(util.pretty_mac(self.value_mask))
+            q.breakable()
+        q.text('}')
+
+class ipv6_src(OXM):
+    type_len = 0x80003410
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!16s", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv6_src()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003410)
+        obj.value = reader.read('!16s')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv6_src {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.pp(self.value)
+            q.breakable()
+        q.text('}')
+
+class ipv6_src_masked(OXM):
+    type_len = 0x80003520
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!16s", self.value))
+        packed.append(struct.pack("!16s", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = ipv6_src_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80003520)
+        obj.value = reader.read('!16s')[0]
+        obj.value_mask = reader.read('!16s')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("ipv6_src_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.pp(self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.pp(self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class metadata(OXM):
+    type_len = 0x80000408
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!Q", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = metadata()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000408)
+        obj.value = reader.read('!Q')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("metadata {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class metadata_masked(OXM):
+    type_len = 0x80000510
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!Q", self.value))
+        packed.append(struct.pack("!Q", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = metadata_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000510)
+        obj.value = reader.read('!Q')[0]
+        obj.value_mask = reader.read('!Q')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("metadata_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class mpls_label(OXM):
+    type_len = 0x80004404
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = mpls_label()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80004404)
+        obj.value = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("mpls_label {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class mpls_label_masked(OXM):
+    type_len = 0x80004508
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!L", self.value))
+        packed.append(struct.pack("!L", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = mpls_label_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80004508)
+        obj.value = reader.read('!L')[0]
+        obj.value_mask = reader.read('!L')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("mpls_label_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class mpls_tc(OXM):
+    type_len = 0x80004601
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = mpls_tc()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80004601)
+        obj.value = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("mpls_tc {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class mpls_tc_masked(OXM):
+    type_len = 0x80004702
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        packed.append(struct.pack("!B", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = mpls_tc_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80004702)
+        obj.value = reader.read('!B')[0]
+        obj.value_mask = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("mpls_tc_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class sctp_dst(OXM):
+    type_len = 0x80002402
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = sctp_dst()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002402)
+        obj.value = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("sctp_dst {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class sctp_dst_masked(OXM):
+    type_len = 0x80002504
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        packed.append(struct.pack("!H", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = sctp_dst_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002504)
+        obj.value = reader.read('!H')[0]
+        obj.value_mask = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("sctp_dst_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class sctp_src(OXM):
+    type_len = 0x80002202
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = sctp_src()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002202)
+        obj.value = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("sctp_src {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class sctp_src_masked(OXM):
+    type_len = 0x80002304
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        packed.append(struct.pack("!H", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = sctp_src_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002304)
+        obj.value = reader.read('!H')[0]
+        obj.value_mask = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("sctp_src_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class tcp_dst(OXM):
+    type_len = 0x80001c02
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = tcp_dst()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001c02)
+        obj.value = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("tcp_dst {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class tcp_dst_masked(OXM):
+    type_len = 0x80001d04
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        packed.append(struct.pack("!H", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = tcp_dst_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001d04)
+        obj.value = reader.read('!H')[0]
+        obj.value_mask = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("tcp_dst_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class tcp_src(OXM):
+    type_len = 0x80001a02
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = tcp_src()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001a02)
+        obj.value = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("tcp_src {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class tcp_src_masked(OXM):
+    type_len = 0x80001b04
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        packed.append(struct.pack("!H", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = tcp_src_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001b04)
+        obj.value = reader.read('!H')[0]
+        obj.value_mask = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("tcp_src_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class udp_dst(OXM):
+    type_len = 0x80002002
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = udp_dst()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002002)
+        obj.value = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("udp_dst {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class udp_dst_masked(OXM):
+    type_len = 0x80002104
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        packed.append(struct.pack("!H", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = udp_dst_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80002104)
+        obj.value = reader.read('!H')[0]
+        obj.value_mask = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("udp_dst_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class udp_src(OXM):
+    type_len = 0x80001e02
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = udp_src()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001e02)
+        obj.value = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("udp_src {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class udp_src_masked(OXM):
+    type_len = 0x80001f04
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        packed.append(struct.pack("!H", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = udp_src_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80001f04)
+        obj.value = reader.read('!H')[0]
+        obj.value_mask = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("udp_src_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class vlan_pcp(OXM):
+    type_len = 0x80000e01
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = vlan_pcp()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000e01)
+        obj.value = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("vlan_pcp {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class vlan_pcp_masked(OXM):
+    type_len = 0x80000f02
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!B", self.value))
+        packed.append(struct.pack("!B", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = vlan_pcp_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000f02)
+        obj.value = reader.read('!B')[0]
+        obj.value_mask = reader.read('!B')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("vlan_pcp_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+class vlan_vid(OXM):
+    type_len = 0x80000c02
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = vlan_vid()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000c02)
+        obj.value = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("vlan_vid {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+class vlan_vid_masked(OXM):
+    type_len = 0x80000d04
+
+    def __init__(self, value=None, value_mask=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 0
+        if value_mask != None:
+            self.value_mask = value_mask
+        else:
+            self.value_mask = 0
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!L", self.type_len))
+        packed.append(struct.pack("!H", self.value))
+        packed.append(struct.pack("!H", self.value_mask))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(buf):
+        obj = vlan_vid_masked()
+        if type(buf) == loxi.generic_util.OFReader:
+            reader = buf
+        else:
+            reader = loxi.generic_util.OFReader(buf)
+        _type_len = reader.read('!L')[0]
+        assert(_type_len == 0x80000d04)
+        obj.value = reader.read('!H')[0]
+        obj.value_mask = reader.read('!H')[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        if self.value_mask != other.value_mask: return False
+        return True
+
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def show(self):
+        import loxi.pp
+        return loxi.pp.pp(self)
+
+    def pretty_print(self, q):
+        q.text("vlan_vid_masked {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+                q.text(","); q.breakable()
+                q.text("value_mask = ");
+                q.text("%#x" % self.value_mask)
+            q.breakable()
+        q.text('}')
+
+
+parsers = {
+    2147483652 : in_port.unpack,
+    2147483912 : in_port_masked.unpack,
+    2147484164 : in_phy_port.unpack,
+    2147484424 : in_phy_port_masked.unpack,
+    2147484680 : metadata.unpack,
+    2147484944 : metadata_masked.unpack,
+    2147485190 : eth_dst.unpack,
+    2147485452 : eth_dst_masked.unpack,
+    2147485702 : eth_src.unpack,
+    2147485964 : eth_src_masked.unpack,
+    2147486210 : eth_type.unpack,
+    2147486468 : eth_type_masked.unpack,
+    2147486722 : vlan_vid.unpack,
+    2147486980 : vlan_vid_masked.unpack,
+    2147487233 : vlan_pcp.unpack,
+    2147487490 : vlan_pcp_masked.unpack,
+    2147487745 : ip_dscp.unpack,
+    2147488002 : ip_dscp_masked.unpack,
+    2147488257 : ip_ecn.unpack,
+    2147488514 : ip_ecn_masked.unpack,
+    2147488769 : ip_proto.unpack,
+    2147489026 : ip_proto_masked.unpack,
+    2147489284 : ipv4_src.unpack,
+    2147489544 : ipv4_src_masked.unpack,
+    2147489796 : ipv4_dst.unpack,
+    2147490056 : ipv4_dst_masked.unpack,
+    2147490306 : tcp_src.unpack,
+    2147490564 : tcp_src_masked.unpack,
+    2147490818 : tcp_dst.unpack,
+    2147491076 : tcp_dst_masked.unpack,
+    2147491330 : udp_src.unpack,
+    2147491588 : udp_src_masked.unpack,
+    2147491842 : udp_dst.unpack,
+    2147492100 : udp_dst_masked.unpack,
+    2147492354 : sctp_src.unpack,
+    2147492612 : sctp_src_masked.unpack,
+    2147492866 : sctp_dst.unpack,
+    2147493124 : sctp_dst_masked.unpack,
+    2147493377 : icmpv4_type.unpack,
+    2147493634 : icmpv4_type_masked.unpack,
+    2147493889 : icmpv4_code.unpack,
+    2147494146 : icmpv4_code_masked.unpack,
+    2147494402 : arp_op.unpack,
+    2147494660 : arp_op_masked.unpack,
+    2147494916 : arp_spa.unpack,
+    2147495176 : arp_spa_masked.unpack,
+    2147495428 : arp_tpa.unpack,
+    2147495688 : arp_tpa_masked.unpack,
+    2147495942 : arp_sha.unpack,
+    2147496204 : arp_sha_masked.unpack,
+    2147496454 : arp_tha.unpack,
+    2147496716 : arp_tha_masked.unpack,
+    2147496976 : ipv6_src.unpack,
+    2147497248 : ipv6_src_masked.unpack,
+    2147497488 : ipv6_dst.unpack,
+    2147497760 : ipv6_dst_masked.unpack,
+    2147497988 : ipv6_flabel.unpack,
+    2147498248 : ipv6_flabel_masked.unpack,
+    2147498497 : icmpv6_type.unpack,
+    2147498754 : icmpv6_type_masked.unpack,
+    2147499009 : icmpv6_code.unpack,
+    2147499266 : icmpv6_code_masked.unpack,
+    2147499536 : ipv6_nd_target.unpack,
+    2147499808 : ipv6_nd_target_masked.unpack,
+    2147500038 : ipv6_nd_sll.unpack,
+    2147500300 : ipv6_nd_sll_masked.unpack,
+    2147500550 : ipv6_nd_tll.unpack,
+    2147500812 : ipv6_nd_tll_masked.unpack,
+    2147501060 : mpls_label.unpack,
+    2147501320 : mpls_label_masked.unpack,
+    2147501569 : mpls_tc.unpack,
+    2147501826 : mpls_tc_masked.unpack,
+}
diff --git a/src/python/loxi/of13/util.py b/src/python/loxi/of13/util.py
new file mode 100644
index 0000000..d431d4c
--- /dev/null
+++ b/src/python/loxi/of13/util.py
@@ -0,0 +1,37 @@
+# Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+# Copyright (c) 2011, 2012 Open Networking Foundation
+# Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+
+# Automatically generated by LOXI from template util.py
+# Do not modify
+
+import loxi
+import const
+import struct
+
+def pretty_mac(mac):
+    return ':'.join(["%02x" % x for x in mac])
+
+def pretty_ipv4(v):
+    return "%d.%d.%d.%d" % ((v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF)
+
+def pretty_flags(v, flag_names):
+    set_flags = []
+    for flag_name in flag_names:
+        flag_value = getattr(const, flag_name)
+        if v & flag_value == flag_value:
+            set_flags.append(flag_name)
+        elif v & flag_value:
+            set_flags.append('%s&%#x' % (flag_name, v & flag_value))
+        v &= ~flag_value
+    if v:
+        set_flags.append("%#x" % v)
+    return '|'.join(set_flags) or '0'
+
+
+def pretty_port(v):
+    named_ports = [(k,v2) for (k,v2) in const.__dict__.iteritems() if k.startswith('OFPP_')]
+    for (k, v2) in named_ports:
+        if v == v2:
+            return k
+    return v
diff --git a/src/python/loxi/pp.py b/src/python/loxi/pp.py
index 852215d..1427ff5 100644
--- a/src/python/loxi/pp.py
+++ b/src/python/loxi/pp.py
@@ -1,3 +1,5 @@
+# Copyright 2013, Big Switch Networks, Inc.
+
 """
 pp - port of Ruby's PP library
 Also based on Lindig, C., & GbR, G. D. (2000). Strictly Pretty.