update pyloxi to 0e07efe22ea803cccfba9ecfe5b6f8ee4e568f28
diff --git a/src/python/loxi/of10/util.py b/src/python/loxi/of10/util.py
index a9b395f..a0e253f 100644
--- a/src/python/loxi/of10/util.py
+++ b/src/python/loxi/of10/util.py
@@ -105,3 +105,10 @@
         except loxi.ProtocolError:
             return None
     return [x for x in loxi.generic_util.unpack_list(reader, deserializer) if x != None]
+
+def pack_checksum_128(value):
+    return struct.pack("!QQ", (value >> 64) & MASK64, value & MASK64)
+
+def unpack_checksum_128(reader):
+    hi, lo = reader.read("!QQ")
+    return (hi << 64) | lo
diff --git a/src/python/loxi/of11/util.py b/src/python/loxi/of11/util.py
index 74a8ad2..80fe37f 100644
--- a/src/python/loxi/of11/util.py
+++ b/src/python/loxi/of11/util.py
@@ -106,3 +106,10 @@
         except loxi.ProtocolError:
             return None
     return [x for x in loxi.generic_util.unpack_list(reader, deserializer) if x != None]
+
+def pack_checksum_128(value):
+    return struct.pack("!QQ", (value >> 64) & MASK64, value & MASK64)
+
+def unpack_checksum_128(reader):
+    hi, lo = reader.read("!QQ")
+    return (hi << 64) | lo
diff --git a/src/python/loxi/of12/util.py b/src/python/loxi/of12/util.py
index 59be12e..0159748 100644
--- a/src/python/loxi/of12/util.py
+++ b/src/python/loxi/of12/util.py
@@ -99,3 +99,10 @@
         except loxi.ProtocolError:
             return None
     return [x for x in loxi.generic_util.unpack_list(reader, deserializer) if x != None]
+
+def pack_checksum_128(value):
+    return struct.pack("!QQ", (value >> 64) & MASK64, value & MASK64)
+
+def unpack_checksum_128(reader):
+    hi, lo = reader.read("!QQ")
+    return (hi << 64) | lo
diff --git a/src/python/loxi/of13/__init__.py b/src/python/loxi/of13/__init__.py
index 2099537..f751290 100644
--- a/src/python/loxi/of13/__init__.py
+++ b/src/python/loxi/of13/__init__.py
@@ -10,6 +10,7 @@
 import instruction
 import oxm
 import meter_band
+import bsn_tlv
 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
index 1c1714c..94bd364 100644
--- a/src/python/loxi/of13/action.py
+++ b/src/python/loxi/of13/action.py
@@ -16,6 +16,7 @@
 import action_id
 import instruction_id
 import meter_band
+import bsn_tlv
 import util
 import loxi.generic_util
 
diff --git a/src/python/loxi/of13/action_id.py b/src/python/loxi/of13/action_id.py
index 431e112..2187a51 100644
--- a/src/python/loxi/of13/action_id.py
+++ b/src/python/loxi/of13/action_id.py
@@ -16,6 +16,7 @@
 import action_id
 import instruction_id
 import meter_band
+import bsn_tlv
 import util
 import loxi.generic_util
 
diff --git a/src/python/loxi/of13/bsn_tlv.py b/src/python/loxi/of13/bsn_tlv.py
new file mode 100644
index 0000000..87cece4
--- /dev/null
+++ b/src/python/loxi/of13/bsn_tlv.py
@@ -0,0 +1,403 @@
+# 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.
+# See the file LICENSE.pyloxi which should have been included in the source distribution
+
+# Automatically generated by LOXI from template module.py
+# Do not modify
+
+import struct
+import loxi
+import const
+import common
+import action
+import instruction
+import oxm
+import action_id
+import instruction_id
+import meter_band
+import bsn_tlv
+import util
+import loxi.generic_util
+
+class bsn_tlv(loxi.OFObject):
+    subtypes = {}
+
+    @staticmethod
+    def unpack(reader):
+        subtype, = reader.peek('!H', 0)
+        try:
+            subclass = bsn_tlv.subtypes[subtype]
+        except KeyError:
+            raise loxi.ProtocolError("unknown bsn_tlv subtype %#x" % subtype)
+        return subclass.unpack(reader)
+
+
+class idle_notification(bsn_tlv):
+    type = 7
+
+    def __init__(self):
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.type))
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 1
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = idle_notification()
+        _type = reader.read("!H")[0]
+        assert(_type == 7)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        return True
+
+    def pretty_print(self, q):
+        q.text("idle_notification {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+            q.breakable()
+        q.text('}')
+
+bsn_tlv.subtypes[7] = idle_notification
+
+class idle_time(bsn_tlv):
+    type = 5
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 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("!Q", self.value))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = idle_time()
+        _type = reader.read("!H")[0]
+        assert(_type == 5)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        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 pretty_print(self, q):
+        q.text("idle_time {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+bsn_tlv.subtypes[5] = idle_time
+
+class ipv4(bsn_tlv):
+    type = 4
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 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.value))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = ipv4()
+        _type = reader.read("!H")[0]
+        assert(_type == 4)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        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 pretty_print(self, q):
+        q.text("ipv4 {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_ipv4(self.value))
+            q.breakable()
+        q.text('}')
+
+bsn_tlv.subtypes[4] = ipv4
+
+class mac(bsn_tlv):
+    type = 1
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = [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 length at index 1
+        packed.append(struct.pack("!6B", *self.value))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = mac()
+        _type = reader.read("!H")[0]
+        assert(_type == 1)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        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 pretty_print(self, q):
+        q.text("mac {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_mac(self.value))
+            q.breakable()
+        q.text('}')
+
+bsn_tlv.subtypes[1] = mac
+
+class port(bsn_tlv):
+    type = 0
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 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(util.pack_port_no(self.value))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = port()
+        _type = reader.read("!H")[0]
+        assert(_type == 0)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        obj.value = util.unpack_port_no(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.value != other.value: return False
+        return True
+
+    def pretty_print(self, q):
+        q.text("port {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text(util.pretty_port(self.value))
+            q.breakable()
+        q.text('}')
+
+bsn_tlv.subtypes[0] = port
+
+class rx_packets(bsn_tlv):
+    type = 2
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 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("!Q", self.value))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = rx_packets()
+        _type = reader.read("!H")[0]
+        assert(_type == 2)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        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 pretty_print(self, q):
+        q.text("rx_packets {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+bsn_tlv.subtypes[2] = rx_packets
+
+class tx_packets(bsn_tlv):
+    type = 3
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 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("!Q", self.value))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = tx_packets()
+        _type = reader.read("!H")[0]
+        assert(_type == 3)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        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 pretty_print(self, q):
+        q.text("tx_packets {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("value = ");
+                q.text("%#x" % self.value)
+            q.breakable()
+        q.text('}')
+
+bsn_tlv.subtypes[3] = tx_packets
+
+class vlan_vid(bsn_tlv):
+    type = 6
+
+    def __init__(self, value=None):
+        if value != None:
+            self.value = value
+        else:
+            self.value = 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("!H", self.value))
+        length = sum([len(x) for x in packed])
+        packed[1] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = vlan_vid()
+        _type = reader.read("!H")[0]
+        assert(_type == 6)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        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 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('}')
+
+bsn_tlv.subtypes[6] = vlan_vid
+
+
diff --git a/src/python/loxi/of13/common.py b/src/python/loxi/of13/common.py
index 8d86467..8080503 100644
--- a/src/python/loxi/of13/common.py
+++ b/src/python/loxi/of13/common.py
@@ -16,9 +16,366 @@
 import action_id
 import instruction_id
 import meter_band
+import bsn_tlv
 import util
 import loxi.generic_util
 
+class bsn_controller_connection(loxi.OFObject):
+
+    def __init__(self, state=None, auxiliary_id=None, role=None, uri=None):
+        if state != None:
+            self.state = state
+        else:
+            self.state = 0
+        if auxiliary_id != None:
+            self.auxiliary_id = auxiliary_id
+        else:
+            self.auxiliary_id = 0
+        if role != None:
+            self.role = role
+        else:
+            self.role = 0
+        if uri != None:
+            self.uri = uri
+        else:
+            self.uri = ""
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!B", self.state))
+        packed.append(struct.pack("!B", self.auxiliary_id))
+        packed.append('\x00' * 2)
+        packed.append(struct.pack("!L", self.role))
+        packed.append(struct.pack("!256s", self.uri))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = bsn_controller_connection()
+        obj.state = reader.read("!B")[0]
+        obj.auxiliary_id = reader.read("!B")[0]
+        reader.skip(2)
+        obj.role = reader.read("!L")[0]
+        obj.uri = reader.read("!256s")[0].rstrip("\x00")
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.state != other.state: return False
+        if self.auxiliary_id != other.auxiliary_id: return False
+        if self.role != other.role: return False
+        if self.uri != other.uri: return False
+        return True
+
+    def pretty_print(self, q):
+        q.text("bsn_controller_connection {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("state = ");
+                q.text("%#x" % self.state)
+                q.text(","); q.breakable()
+                q.text("auxiliary_id = ");
+                q.text("%#x" % self.auxiliary_id)
+                q.text(","); q.breakable()
+                q.text("role = ");
+                q.text("%#x" % self.role)
+                q.text(","); q.breakable()
+                q.text("uri = ");
+                q.pp(self.uri)
+            q.breakable()
+        q.text('}')
+
+
+class bsn_gentable_bucket_stats_entry(loxi.OFObject):
+
+    def __init__(self, checksum=None):
+        if checksum != None:
+            self.checksum = checksum
+        else:
+            self.checksum = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(util.pack_checksum_128(self.checksum))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = bsn_gentable_bucket_stats_entry()
+        obj.checksum = util.unpack_checksum_128(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.checksum != other.checksum: return False
+        return True
+
+    def pretty_print(self, q):
+        q.text("bsn_gentable_bucket_stats_entry {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("checksum = ");
+                q.pp(self.checksum)
+            q.breakable()
+        q.text('}')
+
+
+class bsn_gentable_desc_stats_entry(loxi.OFObject):
+
+    def __init__(self, table_id=None, name=None, buckets_size=None, max_entries=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 buckets_size != None:
+            self.buckets_size = buckets_size
+        else:
+            self.buckets_size = 0
+        if max_entries != None:
+            self.max_entries = max_entries
+        else:
+            self.max_entries = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 0
+        packed.append(struct.pack("!H", self.table_id))
+        packed.append(struct.pack("!32s", self.name))
+        packed.append(struct.pack("!L", self.buckets_size))
+        packed.append(struct.pack("!L", self.max_entries))
+        packed.append('\x00' * 4)
+        length = sum([len(x) for x in packed])
+        packed[0] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = bsn_gentable_desc_stats_entry()
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (0 + 2))
+        obj.table_id = reader.read("!H")[0]
+        obj.name = reader.read("!32s")[0].rstrip("\x00")
+        obj.buckets_size = reader.read("!L")[0]
+        obj.max_entries = reader.read("!L")[0]
+        reader.skip(4)
+        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.buckets_size != other.buckets_size: return False
+        if self.max_entries != other.max_entries: return False
+        return True
+
+    def pretty_print(self, q):
+        q.text("bsn_gentable_desc_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("buckets_size = ");
+                q.text("%#x" % self.buckets_size)
+                q.text(","); q.breakable()
+                q.text("max_entries = ");
+                q.text("%#x" % self.max_entries)
+            q.breakable()
+        q.text('}')
+
+
+class bsn_gentable_entry_desc_stats_entry(loxi.OFObject):
+
+    def __init__(self, checksum=None, key=None, value=None):
+        if checksum != None:
+            self.checksum = checksum
+        else:
+            self.checksum = 0
+        if key != None:
+            self.key = key
+        else:
+            self.key = []
+        if value != None:
+            self.value = value
+        else:
+            self.value = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 0
+        packed.append(struct.pack("!H", 0)) # placeholder for key_length at index 1
+        packed.append(util.pack_checksum_128(self.checksum))
+        packed.append(loxi.generic_util.pack_list(self.key))
+        packed[1] = struct.pack("!H", len(packed[-1]))
+        packed.append(loxi.generic_util.pack_list(self.value))
+        length = sum([len(x) for x in packed])
+        packed[0] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = bsn_gentable_entry_desc_stats_entry()
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (0 + 2))
+        _key_length = reader.read("!H")[0]
+        obj.checksum = util.unpack_checksum_128(reader)
+        obj.key = loxi.generic_util.unpack_list(reader.slice(_key_length), bsn_tlv.bsn_tlv.unpack)
+        obj.value = loxi.generic_util.unpack_list(reader, bsn_tlv.bsn_tlv.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.checksum != other.checksum: return False
+        if self.key != other.key: return False
+        if self.value != other.value: return False
+        return True
+
+    def pretty_print(self, q):
+        q.text("bsn_gentable_entry_desc_stats_entry {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("checksum = ");
+                q.pp(self.checksum)
+                q.text(","); q.breakable()
+                q.text("key = ");
+                q.pp(self.key)
+                q.text(","); q.breakable()
+                q.text("value = ");
+                q.pp(self.value)
+            q.breakable()
+        q.text('}')
+
+
+class bsn_gentable_entry_stats_entry(loxi.OFObject):
+
+    def __init__(self, key=None, stats=None):
+        if key != None:
+            self.key = key
+        else:
+            self.key = []
+        if stats != None:
+            self.stats = stats
+        else:
+            self.stats = []
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", 0)) # placeholder for length at index 0
+        packed.append(struct.pack("!H", 0)) # placeholder for key_length at index 1
+        packed.append(loxi.generic_util.pack_list(self.key))
+        packed[1] = struct.pack("!H", len(packed[-1]))
+        packed.append(loxi.generic_util.pack_list(self.stats))
+        length = sum([len(x) for x in packed])
+        packed[0] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = bsn_gentable_entry_stats_entry()
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (0 + 2))
+        _key_length = reader.read("!H")[0]
+        obj.key = loxi.generic_util.unpack_list(reader.slice(_key_length), bsn_tlv.bsn_tlv.unpack)
+        obj.stats = loxi.generic_util.unpack_list(reader, bsn_tlv.bsn_tlv.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.key != other.key: return False
+        if self.stats != other.stats: return False
+        return True
+
+    def pretty_print(self, q):
+        q.text("bsn_gentable_entry_stats_entry {")
+        with q.group():
+            with q.indent(2):
+                q.breakable()
+                q.text("key = ");
+                q.pp(self.key)
+                q.text(","); q.breakable()
+                q.text("stats = ");
+                q.pp(self.stats)
+            q.breakable()
+        q.text('}')
+
+
+class bsn_gentable_stats_entry(loxi.OFObject):
+
+    def __init__(self, table_id=None, entry_count=None, checksum=None):
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if entry_count != None:
+            self.entry_count = entry_count
+        else:
+            self.entry_count = 0
+        if checksum != None:
+            self.checksum = checksum
+        else:
+            self.checksum = 0
+        return
+
+    def pack(self):
+        packed = []
+        packed.append(struct.pack("!H", self.table_id))
+        packed.append('\x00' * 2)
+        packed.append(struct.pack("!L", self.entry_count))
+        packed.append(util.pack_checksum_128(self.checksum))
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = bsn_gentable_stats_entry()
+        obj.table_id = reader.read("!H")[0]
+        reader.skip(2)
+        obj.entry_count = reader.read("!L")[0]
+        obj.checksum = util.unpack_checksum_128(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.entry_count != other.entry_count: return False
+        if self.checksum != other.checksum: return False
+        return True
+
+    def pretty_print(self, q):
+        q.text("bsn_gentable_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("entry_count = ");
+                q.text("%#x" % self.entry_count)
+                q.text(","); q.breakable()
+                q.text("checksum = ");
+                q.pp(self.checksum)
+            q.breakable()
+        q.text('}')
+
+
 class bsn_interface(loxi.OFObject):
 
     def __init__(self, hw_addr=None, name=None, ipv4_addr=None, ipv4_netmask=None):
diff --git a/src/python/loxi/of13/const.py b/src/python/loxi/of13/const.py
index af982a5..3e80b96 100644
--- a/src/python/loxi/of13/const.py
+++ b/src/python/loxi/of13/const.py
@@ -217,6 +217,26 @@
     13: 'OFPBRC_MULTIPART_BUFFER_OVERFLOW',
 }
 
+# Identifiers from group ofp_bsn_controller_connection_state
+OFP_BSN_CONTROLLER_CONNECTION_STATE_DISCONNECTED = 0
+OFP_BSN_CONTROLLER_CONNECTION_STATE_CONNECTED = 1
+
+ofp_bsn_controller_connection_state_map = {
+    0: 'OFP_BSN_CONTROLLER_CONNECTION_STATE_DISCONNECTED',
+    1: 'OFP_BSN_CONTROLLER_CONNECTION_STATE_CONNECTED',
+}
+
+# Identifiers from group ofp_bsn_controller_role_reason
+OFP_BSN_CONTROLLER_ROLE_REASON_MASTER_REQUEST = 0
+OFP_BSN_CONTROLLER_ROLE_REASON_CONFIG = 1
+OFP_BSN_CONTROLLER_ROLE_REASON_EXPERIMENTER = 2
+
+ofp_bsn_controller_role_reason_map = {
+    0: 'OFP_BSN_CONTROLLER_ROLE_REASON_MASTER_REQUEST',
+    1: 'OFP_BSN_CONTROLLER_ROLE_REASON_CONFIG',
+    2: 'OFP_BSN_CONTROLLER_ROLE_REASON_EXPERIMENTER',
+}
+
 # Identifiers from group ofp_bsn_port_counter
 OFP_BSN_PORT_COUNTER_RX_BYTES = 0
 OFP_BSN_PORT_COUNTER_RX_PACKETS_UNICAST = 1
@@ -665,6 +685,7 @@
 OFPR_BSN_STATION_MOVE = 129
 OFPR_BSN_BAD_VLAN = 130
 OFPR_BSN_DESTINATION_LOOKUP_FAILURE = 131
+OFPR_BSN_NO_ROUTE = 132
 
 ofp_packet_in_reason_map = {
     0: 'OFPR_NO_MATCH',
@@ -674,6 +695,7 @@
     129: 'OFPR_BSN_STATION_MOVE',
     130: 'OFPR_BSN_BAD_VLAN',
     131: 'OFPR_BSN_DESTINATION_LOOKUP_FAILURE',
+    132: 'OFPR_BSN_NO_ROUTE',
 }
 
 # Identifiers from group ofp_port
diff --git a/src/python/loxi/of13/instruction.py b/src/python/loxi/of13/instruction.py
index e36cc73..7004dba 100644
--- a/src/python/loxi/of13/instruction.py
+++ b/src/python/loxi/of13/instruction.py
@@ -16,6 +16,7 @@
 import action_id
 import instruction_id
 import meter_band
+import bsn_tlv
 import util
 import loxi.generic_util
 
diff --git a/src/python/loxi/of13/instruction_id.py b/src/python/loxi/of13/instruction_id.py
index 752788a..79bae4e 100644
--- a/src/python/loxi/of13/instruction_id.py
+++ b/src/python/loxi/of13/instruction_id.py
@@ -16,6 +16,7 @@
 import action_id
 import instruction_id
 import meter_band
+import bsn_tlv
 import util
 import loxi.generic_util
 
diff --git a/src/python/loxi/of13/message.py b/src/python/loxi/of13/message.py
index 2737bd1..84d34a9 100644
--- a/src/python/loxi/of13/message.py
+++ b/src/python/loxi/of13/message.py
@@ -16,6 +16,7 @@
 import action_id
 import instruction_id
 import meter_band
+import bsn_tlv
 import util
 import loxi.generic_util
 
@@ -1522,6 +1523,140 @@
 
 bsn_header.subtypes[18] = bsn_bw_enable_set_request
 
+class bsn_controller_connections_reply(bsn_header):
+    version = 4
+    type = 4
+    experimenter = 6035143
+    subtype = 57
+
+    def __init__(self, xid=None, connections=None):
+        if xid != None:
+            self.xid = xid
+        else:
+            self.xid = None
+        if connections != None:
+            self.connections = connections
+        else:
+            self.connections = []
+        return
+
+    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(loxi.generic_util.pack_list(self.connections))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = bsn_controller_connections_reply()
+        _version = reader.read("!B")[0]
+        assert(_version == 4)
+        _type = reader.read("!B")[0]
+        assert(_type == 4)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        obj.xid = reader.read("!L")[0]
+        _experimenter = reader.read("!L")[0]
+        assert(_experimenter == 6035143)
+        _subtype = reader.read("!L")[0]
+        assert(_subtype == 57)
+        obj.connections = loxi.generic_util.unpack_list(reader, common.bsn_controller_connection.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.xid != other.xid: return False
+        if self.connections != other.connections: return False
+        return True
+
+    def pretty_print(self, q):
+        q.text("bsn_controller_connections_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("connections = ");
+                q.pp(self.connections)
+            q.breakable()
+        q.text('}')
+
+bsn_header.subtypes[57] = bsn_controller_connections_reply
+
+class bsn_controller_connections_request(bsn_header):
+    version = 4
+    type = 4
+    experimenter = 6035143
+    subtype = 56
+
+    def __init__(self, xid=None):
+        if xid != None:
+            self.xid = xid
+        else:
+            self.xid = None
+        return
+
+    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(reader):
+        obj = bsn_controller_connections_request()
+        _version = reader.read("!B")[0]
+        assert(_version == 4)
+        _type = reader.read("!B")[0]
+        assert(_type == 4)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        obj.xid = reader.read("!L")[0]
+        _experimenter = reader.read("!L")[0]
+        assert(_experimenter == 6035143)
+        _subtype = reader.read("!L")[0]
+        assert(_subtype == 56)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.xid != other.xid: return False
+        return True
+
+    def pretty_print(self, q):
+        q.text("bsn_controller_connections_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('}')
+
+bsn_header.subtypes[56] = bsn_controller_connections_request
+
 class bsn_flow_idle(bsn_header):
     version = 4
     type = 4
@@ -1914,6 +2049,1425 @@
 
 bsn_header.subtypes[36] = bsn_flow_idle_enable_set_request
 
+class experimenter_stats_reply(stats_reply):
+    subtypes = {}
+
+    @staticmethod
+    def unpack(reader):
+        subtype, = reader.peek('!L', 16)
+        try:
+            subclass = experimenter_stats_reply.subtypes[subtype]
+        except KeyError:
+            raise loxi.ProtocolError("unknown experimenter_stats_reply stats_reply message subtype %#x" % subtype)
+        return subclass.unpack(reader)
+
+stats_reply.subtypes[65535] = experimenter_stats_reply
+
+class bsn_stats_reply(experimenter_stats_reply):
+    subtypes = {}
+
+    @staticmethod
+    def unpack(reader):
+        subtype, = reader.peek('!L', 20)
+        try:
+            subclass = bsn_stats_reply.subtypes[subtype]
+        except KeyError:
+            raise loxi.ProtocolError("unknown bsn_stats_reply experimenter_stats_reply stats_reply message subtype %#x" % subtype)
+        return subclass.unpack(reader)
+
+experimenter_stats_reply.subtypes[6035143] = bsn_stats_reply
+
+class bsn_gentable_bucket_stats_reply(bsn_stats_reply):
+    version = 4
+    type = 19
+    stats_type = 65535
+    experimenter = 6035143
+    subtype = 5
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        if xid != None:
+            self.xid = xid
+        else:
+            self.xid = None
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+        return
+
+    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(loxi.generic_util.pack_list(self.entries))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = bsn_gentable_bucket_stats_reply()
+        _version = reader.read("!B")[0]
+        assert(_version == 4)
+        _type = reader.read("!B")[0]
+        assert(_type == 19)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        obj.xid = reader.read("!L")[0]
+        _stats_type = reader.read("!H")[0]
+        assert(_stats_type == 65535)
+        obj.flags = reader.read("!H")[0]
+        reader.skip(4)
+        _experimenter = reader.read("!L")[0]
+        assert(_experimenter == 6035143)
+        _subtype = reader.read("!L")[0]
+        assert(_subtype == 5)
+        obj.entries = loxi.generic_util.unpack_list(reader, common.bsn_gentable_bucket_stats_entry.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): 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 pretty_print(self, q):
+        q.text("bsn_gentable_bucket_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('}')
+
+bsn_stats_reply.subtypes[5] = bsn_gentable_bucket_stats_reply
+
+class experimenter_stats_request(stats_request):
+    subtypes = {}
+
+    @staticmethod
+    def unpack(reader):
+        subtype, = reader.peek('!L', 16)
+        try:
+            subclass = experimenter_stats_request.subtypes[subtype]
+        except KeyError:
+            raise loxi.ProtocolError("unknown experimenter_stats_request stats_request message subtype %#x" % subtype)
+        return subclass.unpack(reader)
+
+stats_request.subtypes[65535] = experimenter_stats_request
+
+class bsn_stats_request(experimenter_stats_request):
+    subtypes = {}
+
+    @staticmethod
+    def unpack(reader):
+        subtype, = reader.peek('!L', 20)
+        try:
+            subclass = bsn_stats_request.subtypes[subtype]
+        except KeyError:
+            raise loxi.ProtocolError("unknown bsn_stats_request experimenter_stats_request stats_request message subtype %#x" % subtype)
+        return subclass.unpack(reader)
+
+experimenter_stats_request.subtypes[6035143] = bsn_stats_request
+
+class bsn_gentable_bucket_stats_request(bsn_stats_request):
+    version = 4
+    type = 18
+    stats_type = 65535
+    experimenter = 6035143
+    subtype = 5
+
+    def __init__(self, xid=None, flags=None, table_id=None):
+        if xid != None:
+            self.xid = xid
+        else:
+            self.xid = None
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        return
+
+    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(struct.pack("!H", self.table_id))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = bsn_gentable_bucket_stats_request()
+        _version = reader.read("!B")[0]
+        assert(_version == 4)
+        _type = reader.read("!B")[0]
+        assert(_type == 18)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        obj.xid = reader.read("!L")[0]
+        _stats_type = reader.read("!H")[0]
+        assert(_stats_type == 65535)
+        obj.flags = reader.read("!H")[0]
+        reader.skip(4)
+        _experimenter = reader.read("!L")[0]
+        assert(_experimenter == 6035143)
+        _subtype = reader.read("!L")[0]
+        assert(_subtype == 5)
+        obj.table_id = reader.read("!H")[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): 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
+        return True
+
+    def pretty_print(self, q):
+        q.text("bsn_gentable_bucket_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.breakable()
+        q.text('}')
+
+bsn_stats_request.subtypes[5] = bsn_gentable_bucket_stats_request
+
+class bsn_gentable_clear_reply(bsn_header):
+    version = 4
+    type = 4
+    experimenter = 6035143
+    subtype = 49
+
+    def __init__(self, xid=None, table_id=None, deleted_count=None, error_count=None):
+        if xid != None:
+            self.xid = xid
+        else:
+            self.xid = None
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if deleted_count != None:
+            self.deleted_count = deleted_count
+        else:
+            self.deleted_count = 0
+        if error_count != None:
+            self.error_count = error_count
+        else:
+            self.error_count = 0
+        return
+
+    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("!H", self.table_id))
+        packed.append('\x00' * 2)
+        packed.append(struct.pack("!L", self.deleted_count))
+        packed.append(struct.pack("!L", self.error_count))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = bsn_gentable_clear_reply()
+        _version = reader.read("!B")[0]
+        assert(_version == 4)
+        _type = reader.read("!B")[0]
+        assert(_type == 4)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        obj.xid = reader.read("!L")[0]
+        _experimenter = reader.read("!L")[0]
+        assert(_experimenter == 6035143)
+        _subtype = reader.read("!L")[0]
+        assert(_subtype == 49)
+        obj.table_id = reader.read("!H")[0]
+        reader.skip(2)
+        obj.deleted_count = reader.read("!L")[0]
+        obj.error_count = reader.read("!L")[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.xid != other.xid: return False
+        if self.table_id != other.table_id: return False
+        if self.deleted_count != other.deleted_count: return False
+        if self.error_count != other.error_count: return False
+        return True
+
+    def pretty_print(self, q):
+        q.text("bsn_gentable_clear_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("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("deleted_count = ");
+                q.text("%#x" % self.deleted_count)
+                q.text(","); q.breakable()
+                q.text("error_count = ");
+                q.text("%#x" % self.error_count)
+            q.breakable()
+        q.text('}')
+
+bsn_header.subtypes[49] = bsn_gentable_clear_reply
+
+class bsn_gentable_clear_request(bsn_header):
+    version = 4
+    type = 4
+    experimenter = 6035143
+    subtype = 48
+
+    def __init__(self, xid=None, table_id=None, checksum=None, checksum_mask=None):
+        if xid != None:
+            self.xid = xid
+        else:
+            self.xid = None
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if checksum != None:
+            self.checksum = checksum
+        else:
+            self.checksum = 0
+        if checksum_mask != None:
+            self.checksum_mask = checksum_mask
+        else:
+            self.checksum_mask = 0
+        return
+
+    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("!H", self.table_id))
+        packed.append('\x00' * 2)
+        packed.append(util.pack_checksum_128(self.checksum))
+        packed.append(util.pack_checksum_128(self.checksum_mask))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = bsn_gentable_clear_request()
+        _version = reader.read("!B")[0]
+        assert(_version == 4)
+        _type = reader.read("!B")[0]
+        assert(_type == 4)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        obj.xid = reader.read("!L")[0]
+        _experimenter = reader.read("!L")[0]
+        assert(_experimenter == 6035143)
+        _subtype = reader.read("!L")[0]
+        assert(_subtype == 48)
+        obj.table_id = reader.read("!H")[0]
+        reader.skip(2)
+        obj.checksum = util.unpack_checksum_128(reader)
+        obj.checksum_mask = util.unpack_checksum_128(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.xid != other.xid: return False
+        if self.table_id != other.table_id: return False
+        if self.checksum != other.checksum: return False
+        if self.checksum_mask != other.checksum_mask: return False
+        return True
+
+    def pretty_print(self, q):
+        q.text("bsn_gentable_clear_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("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("checksum = ");
+                q.pp(self.checksum)
+                q.text(","); q.breakable()
+                q.text("checksum_mask = ");
+                q.pp(self.checksum_mask)
+            q.breakable()
+        q.text('}')
+
+bsn_header.subtypes[48] = bsn_gentable_clear_request
+
+class bsn_gentable_desc_stats_reply(bsn_stats_reply):
+    version = 4
+    type = 19
+    stats_type = 65535
+    experimenter = 6035143
+    subtype = 4
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        if xid != None:
+            self.xid = xid
+        else:
+            self.xid = None
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+        return
+
+    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(loxi.generic_util.pack_list(self.entries))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = bsn_gentable_desc_stats_reply()
+        _version = reader.read("!B")[0]
+        assert(_version == 4)
+        _type = reader.read("!B")[0]
+        assert(_type == 19)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        obj.xid = reader.read("!L")[0]
+        _stats_type = reader.read("!H")[0]
+        assert(_stats_type == 65535)
+        obj.flags = reader.read("!H")[0]
+        reader.skip(4)
+        _experimenter = reader.read("!L")[0]
+        assert(_experimenter == 6035143)
+        _subtype = reader.read("!L")[0]
+        assert(_subtype == 4)
+        obj.entries = loxi.generic_util.unpack_list(reader, common.bsn_gentable_desc_stats_entry.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): 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 pretty_print(self, q):
+        q.text("bsn_gentable_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('}')
+
+bsn_stats_reply.subtypes[4] = bsn_gentable_desc_stats_reply
+
+class bsn_gentable_desc_stats_request(bsn_stats_request):
+    version = 4
+    type = 18
+    stats_type = 65535
+    experimenter = 6035143
+    subtype = 4
+
+    def __init__(self, xid=None, flags=None):
+        if xid != None:
+            self.xid = xid
+        else:
+            self.xid = None
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        return
+
+    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))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = bsn_gentable_desc_stats_request()
+        _version = reader.read("!B")[0]
+        assert(_version == 4)
+        _type = reader.read("!B")[0]
+        assert(_type == 18)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        obj.xid = reader.read("!L")[0]
+        _stats_type = reader.read("!H")[0]
+        assert(_stats_type == 65535)
+        obj.flags = reader.read("!H")[0]
+        reader.skip(4)
+        _experimenter = reader.read("!L")[0]
+        assert(_experimenter == 6035143)
+        _subtype = reader.read("!L")[0]
+        assert(_subtype == 4)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        return True
+
+    def pretty_print(self, q):
+        q.text("bsn_gentable_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('}')
+
+bsn_stats_request.subtypes[4] = bsn_gentable_desc_stats_request
+
+class bsn_gentable_entry_add(bsn_header):
+    version = 4
+    type = 4
+    experimenter = 6035143
+    subtype = 46
+
+    def __init__(self, xid=None, table_id=None, checksum=None, key=None, value=None):
+        if xid != None:
+            self.xid = xid
+        else:
+            self.xid = None
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if checksum != None:
+            self.checksum = checksum
+        else:
+            self.checksum = 0
+        if key != None:
+            self.key = key
+        else:
+            self.key = []
+        if value != None:
+            self.value = value
+        else:
+            self.value = []
+        return
+
+    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("!H", self.table_id))
+        packed.append(struct.pack("!H", 0)) # placeholder for key_length at index 7
+        packed.append(util.pack_checksum_128(self.checksum))
+        packed.append(loxi.generic_util.pack_list(self.key))
+        packed[7] = struct.pack("!H", len(packed[-1]))
+        packed.append(loxi.generic_util.pack_list(self.value))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = bsn_gentable_entry_add()
+        _version = reader.read("!B")[0]
+        assert(_version == 4)
+        _type = reader.read("!B")[0]
+        assert(_type == 4)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        obj.xid = reader.read("!L")[0]
+        _experimenter = reader.read("!L")[0]
+        assert(_experimenter == 6035143)
+        _subtype = reader.read("!L")[0]
+        assert(_subtype == 46)
+        obj.table_id = reader.read("!H")[0]
+        _key_length = reader.read("!H")[0]
+        obj.checksum = util.unpack_checksum_128(reader)
+        obj.key = loxi.generic_util.unpack_list(reader.slice(_key_length), bsn_tlv.bsn_tlv.unpack)
+        obj.value = loxi.generic_util.unpack_list(reader, bsn_tlv.bsn_tlv.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.xid != other.xid: return False
+        if self.table_id != other.table_id: return False
+        if self.checksum != other.checksum: return False
+        if self.key != other.key: return False
+        if self.value != other.value: return False
+        return True
+
+    def pretty_print(self, q):
+        q.text("bsn_gentable_entry_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("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("checksum = ");
+                q.pp(self.checksum)
+                q.text(","); q.breakable()
+                q.text("key = ");
+                q.pp(self.key)
+                q.text(","); q.breakable()
+                q.text("value = ");
+                q.pp(self.value)
+            q.breakable()
+        q.text('}')
+
+bsn_header.subtypes[46] = bsn_gentable_entry_add
+
+class bsn_gentable_entry_delete(bsn_header):
+    version = 4
+    type = 4
+    experimenter = 6035143
+    subtype = 47
+
+    def __init__(self, xid=None, table_id=None, key=None):
+        if xid != None:
+            self.xid = xid
+        else:
+            self.xid = None
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if key != None:
+            self.key = key
+        else:
+            self.key = []
+        return
+
+    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("!H", self.table_id))
+        packed.append(loxi.generic_util.pack_list(self.key))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = bsn_gentable_entry_delete()
+        _version = reader.read("!B")[0]
+        assert(_version == 4)
+        _type = reader.read("!B")[0]
+        assert(_type == 4)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        obj.xid = reader.read("!L")[0]
+        _experimenter = reader.read("!L")[0]
+        assert(_experimenter == 6035143)
+        _subtype = reader.read("!L")[0]
+        assert(_subtype == 47)
+        obj.table_id = reader.read("!H")[0]
+        obj.key = loxi.generic_util.unpack_list(reader, bsn_tlv.bsn_tlv.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.xid != other.xid: return False
+        if self.table_id != other.table_id: return False
+        if self.key != other.key: return False
+        return True
+
+    def pretty_print(self, q):
+        q.text("bsn_gentable_entry_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("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("key = ");
+                q.pp(self.key)
+            q.breakable()
+        q.text('}')
+
+bsn_header.subtypes[47] = bsn_gentable_entry_delete
+
+class bsn_gentable_entry_desc_stats_reply(bsn_stats_reply):
+    version = 4
+    type = 19
+    stats_type = 65535
+    experimenter = 6035143
+    subtype = 2
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        if xid != None:
+            self.xid = xid
+        else:
+            self.xid = None
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+        return
+
+    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(loxi.generic_util.pack_list(self.entries))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = bsn_gentable_entry_desc_stats_reply()
+        _version = reader.read("!B")[0]
+        assert(_version == 4)
+        _type = reader.read("!B")[0]
+        assert(_type == 19)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        obj.xid = reader.read("!L")[0]
+        _stats_type = reader.read("!H")[0]
+        assert(_stats_type == 65535)
+        obj.flags = reader.read("!H")[0]
+        reader.skip(4)
+        _experimenter = reader.read("!L")[0]
+        assert(_experimenter == 6035143)
+        _subtype = reader.read("!L")[0]
+        assert(_subtype == 2)
+        obj.entries = loxi.generic_util.unpack_list(reader, common.bsn_gentable_entry_desc_stats_entry.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): 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 pretty_print(self, q):
+        q.text("bsn_gentable_entry_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('}')
+
+bsn_stats_reply.subtypes[2] = bsn_gentable_entry_desc_stats_reply
+
+class bsn_gentable_entry_desc_stats_request(bsn_stats_request):
+    version = 4
+    type = 18
+    stats_type = 65535
+    experimenter = 6035143
+    subtype = 2
+
+    def __init__(self, xid=None, flags=None, table_id=None, checksum=None, checksum_mask=None):
+        if xid != None:
+            self.xid = xid
+        else:
+            self.xid = None
+        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 checksum != None:
+            self.checksum = checksum
+        else:
+            self.checksum = 0
+        if checksum_mask != None:
+            self.checksum_mask = checksum_mask
+        else:
+            self.checksum_mask = 0
+        return
+
+    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(struct.pack("!H", self.table_id))
+        packed.append('\x00' * 2)
+        packed.append(util.pack_checksum_128(self.checksum))
+        packed.append(util.pack_checksum_128(self.checksum_mask))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = bsn_gentable_entry_desc_stats_request()
+        _version = reader.read("!B")[0]
+        assert(_version == 4)
+        _type = reader.read("!B")[0]
+        assert(_type == 18)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        obj.xid = reader.read("!L")[0]
+        _stats_type = reader.read("!H")[0]
+        assert(_stats_type == 65535)
+        obj.flags = reader.read("!H")[0]
+        reader.skip(4)
+        _experimenter = reader.read("!L")[0]
+        assert(_experimenter == 6035143)
+        _subtype = reader.read("!L")[0]
+        assert(_subtype == 2)
+        obj.table_id = reader.read("!H")[0]
+        reader.skip(2)
+        obj.checksum = util.unpack_checksum_128(reader)
+        obj.checksum_mask = util.unpack_checksum_128(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): 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.checksum != other.checksum: return False
+        if self.checksum_mask != other.checksum_mask: return False
+        return True
+
+    def pretty_print(self, q):
+        q.text("bsn_gentable_entry_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.text(","); q.breakable()
+                q.text("table_id = ");
+                q.text("%#x" % self.table_id)
+                q.text(","); q.breakable()
+                q.text("checksum = ");
+                q.pp(self.checksum)
+                q.text(","); q.breakable()
+                q.text("checksum_mask = ");
+                q.pp(self.checksum_mask)
+            q.breakable()
+        q.text('}')
+
+bsn_stats_request.subtypes[2] = bsn_gentable_entry_desc_stats_request
+
+class bsn_gentable_entry_stats_reply(bsn_stats_reply):
+    version = 4
+    type = 19
+    stats_type = 65535
+    experimenter = 6035143
+    subtype = 3
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        if xid != None:
+            self.xid = xid
+        else:
+            self.xid = None
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+        return
+
+    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(loxi.generic_util.pack_list(self.entries))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = bsn_gentable_entry_stats_reply()
+        _version = reader.read("!B")[0]
+        assert(_version == 4)
+        _type = reader.read("!B")[0]
+        assert(_type == 19)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        obj.xid = reader.read("!L")[0]
+        _stats_type = reader.read("!H")[0]
+        assert(_stats_type == 65535)
+        obj.flags = reader.read("!H")[0]
+        reader.skip(4)
+        _experimenter = reader.read("!L")[0]
+        assert(_experimenter == 6035143)
+        _subtype = reader.read("!L")[0]
+        assert(_subtype == 3)
+        obj.entries = loxi.generic_util.unpack_list(reader, common.bsn_gentable_entry_stats_entry.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): 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 pretty_print(self, q):
+        q.text("bsn_gentable_entry_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('}')
+
+bsn_stats_reply.subtypes[3] = bsn_gentable_entry_stats_reply
+
+class bsn_gentable_entry_stats_request(bsn_stats_request):
+    version = 4
+    type = 18
+    stats_type = 65535
+    experimenter = 6035143
+    subtype = 3
+
+    def __init__(self, xid=None, flags=None, table_id=None, checksum=None, checksum_mask=None):
+        if xid != None:
+            self.xid = xid
+        else:
+            self.xid = None
+        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 checksum != None:
+            self.checksum = checksum
+        else:
+            self.checksum = 0
+        if checksum_mask != None:
+            self.checksum_mask = checksum_mask
+        else:
+            self.checksum_mask = 0
+        return
+
+    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(struct.pack("!H", self.table_id))
+        packed.append('\x00' * 2)
+        packed.append(util.pack_checksum_128(self.checksum))
+        packed.append(util.pack_checksum_128(self.checksum_mask))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = bsn_gentable_entry_stats_request()
+        _version = reader.read("!B")[0]
+        assert(_version == 4)
+        _type = reader.read("!B")[0]
+        assert(_type == 18)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        obj.xid = reader.read("!L")[0]
+        _stats_type = reader.read("!H")[0]
+        assert(_stats_type == 65535)
+        obj.flags = reader.read("!H")[0]
+        reader.skip(4)
+        _experimenter = reader.read("!L")[0]
+        assert(_experimenter == 6035143)
+        _subtype = reader.read("!L")[0]
+        assert(_subtype == 3)
+        obj.table_id = reader.read("!H")[0]
+        reader.skip(2)
+        obj.checksum = util.unpack_checksum_128(reader)
+        obj.checksum_mask = util.unpack_checksum_128(reader)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): 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.checksum != other.checksum: return False
+        if self.checksum_mask != other.checksum_mask: return False
+        return True
+
+    def pretty_print(self, q):
+        q.text("bsn_gentable_entry_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("checksum = ");
+                q.pp(self.checksum)
+                q.text(","); q.breakable()
+                q.text("checksum_mask = ");
+                q.pp(self.checksum_mask)
+            q.breakable()
+        q.text('}')
+
+bsn_stats_request.subtypes[3] = bsn_gentable_entry_stats_request
+
+class bsn_gentable_set_buckets_size(bsn_header):
+    version = 4
+    type = 4
+    experimenter = 6035143
+    subtype = 50
+
+    def __init__(self, xid=None, table_id=None, buckets_size=None):
+        if xid != None:
+            self.xid = xid
+        else:
+            self.xid = None
+        if table_id != None:
+            self.table_id = table_id
+        else:
+            self.table_id = 0
+        if buckets_size != None:
+            self.buckets_size = buckets_size
+        else:
+            self.buckets_size = 0
+        return
+
+    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("!H", self.table_id))
+        packed.append('\x00' * 2)
+        packed.append(struct.pack("!L", self.buckets_size))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = bsn_gentable_set_buckets_size()
+        _version = reader.read("!B")[0]
+        assert(_version == 4)
+        _type = reader.read("!B")[0]
+        assert(_type == 4)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        obj.xid = reader.read("!L")[0]
+        _experimenter = reader.read("!L")[0]
+        assert(_experimenter == 6035143)
+        _subtype = reader.read("!L")[0]
+        assert(_subtype == 50)
+        obj.table_id = reader.read("!H")[0]
+        reader.skip(2)
+        obj.buckets_size = reader.read("!L")[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.xid != other.xid: return False
+        if self.table_id != other.table_id: return False
+        if self.buckets_size != other.buckets_size: return False
+        return True
+
+    def pretty_print(self, q):
+        q.text("bsn_gentable_set_buckets_size {")
+        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("buckets_size = ");
+                q.text("%#x" % self.buckets_size)
+            q.breakable()
+        q.text('}')
+
+bsn_header.subtypes[50] = bsn_gentable_set_buckets_size
+
+class bsn_gentable_stats_reply(bsn_stats_reply):
+    version = 4
+    type = 19
+    stats_type = 65535
+    experimenter = 6035143
+    subtype = 7
+
+    def __init__(self, xid=None, flags=None, entries=None):
+        if xid != None:
+            self.xid = xid
+        else:
+            self.xid = None
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        if entries != None:
+            self.entries = entries
+        else:
+            self.entries = []
+        return
+
+    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(loxi.generic_util.pack_list(self.entries))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = bsn_gentable_stats_reply()
+        _version = reader.read("!B")[0]
+        assert(_version == 4)
+        _type = reader.read("!B")[0]
+        assert(_type == 19)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        obj.xid = reader.read("!L")[0]
+        _stats_type = reader.read("!H")[0]
+        assert(_stats_type == 65535)
+        obj.flags = reader.read("!H")[0]
+        reader.skip(4)
+        _experimenter = reader.read("!L")[0]
+        assert(_experimenter == 6035143)
+        _subtype = reader.read("!L")[0]
+        assert(_subtype == 7)
+        obj.entries = loxi.generic_util.unpack_list(reader, common.bsn_gentable_stats_entry.unpack)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): 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 pretty_print(self, q):
+        q.text("bsn_gentable_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('}')
+
+bsn_stats_reply.subtypes[7] = bsn_gentable_stats_reply
+
+class bsn_gentable_stats_request(bsn_stats_request):
+    version = 4
+    type = 18
+    stats_type = 65535
+    experimenter = 6035143
+    subtype = 7
+
+    def __init__(self, xid=None, flags=None):
+        if xid != None:
+            self.xid = xid
+        else:
+            self.xid = None
+        if flags != None:
+            self.flags = flags
+        else:
+            self.flags = 0
+        return
+
+    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))
+        length = sum([len(x) for x in packed])
+        packed[2] = struct.pack("!H", length)
+        return ''.join(packed)
+
+    @staticmethod
+    def unpack(reader):
+        obj = bsn_gentable_stats_request()
+        _version = reader.read("!B")[0]
+        assert(_version == 4)
+        _type = reader.read("!B")[0]
+        assert(_type == 18)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        obj.xid = reader.read("!L")[0]
+        _stats_type = reader.read("!H")[0]
+        assert(_stats_type == 65535)
+        obj.flags = reader.read("!H")[0]
+        reader.skip(4)
+        _experimenter = reader.read("!L")[0]
+        assert(_experimenter == 6035143)
+        _subtype = reader.read("!L")[0]
+        assert(_subtype == 7)
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.xid != other.xid: return False
+        if self.flags != other.flags: return False
+        return True
+
+    def pretty_print(self, q):
+        q.text("bsn_gentable_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('}')
+
+bsn_stats_request.subtypes[7] = bsn_gentable_stats_request
+
 class bsn_get_interfaces_reply(bsn_header):
     version = 4
     type = 4
@@ -2514,34 +4068,6 @@
 
 bsn_header.subtypes[43] = bsn_lacp_convergence_notif
 
-class experimenter_stats_reply(stats_reply):
-    subtypes = {}
-
-    @staticmethod
-    def unpack(reader):
-        subtype, = reader.peek('!L', 16)
-        try:
-            subclass = experimenter_stats_reply.subtypes[subtype]
-        except KeyError:
-            raise loxi.ProtocolError("unknown experimenter_stats_reply stats_reply message subtype %#x" % subtype)
-        return subclass.unpack(reader)
-
-stats_reply.subtypes[65535] = experimenter_stats_reply
-
-class bsn_stats_reply(experimenter_stats_reply):
-    subtypes = {}
-
-    @staticmethod
-    def unpack(reader):
-        subtype, = reader.peek('!L', 20)
-        try:
-            subclass = bsn_stats_reply.subtypes[subtype]
-        except KeyError:
-            raise loxi.ProtocolError("unknown bsn_stats_reply experimenter_stats_reply stats_reply message subtype %#x" % subtype)
-        return subclass.unpack(reader)
-
-experimenter_stats_reply.subtypes[6035143] = bsn_stats_reply
-
 class bsn_lacp_stats_reply(bsn_stats_reply):
     version = 4
     type = 19
@@ -2630,34 +4156,6 @@
 
 bsn_stats_reply.subtypes[1] = bsn_lacp_stats_reply
 
-class experimenter_stats_request(stats_request):
-    subtypes = {}
-
-    @staticmethod
-    def unpack(reader):
-        subtype, = reader.peek('!L', 16)
-        try:
-            subclass = experimenter_stats_request.subtypes[subtype]
-        except KeyError:
-            raise loxi.ProtocolError("unknown experimenter_stats_request stats_request message subtype %#x" % subtype)
-        return subclass.unpack(reader)
-
-stats_request.subtypes[65535] = experimenter_stats_request
-
-class bsn_stats_request(experimenter_stats_request):
-    subtypes = {}
-
-    @staticmethod
-    def unpack(reader):
-        subtype, = reader.peek('!L', 20)
-        try:
-            subclass = bsn_stats_request.subtypes[subtype]
-        except KeyError:
-            raise loxi.ProtocolError("unknown bsn_stats_request experimenter_stats_request stats_request message subtype %#x" % subtype)
-        return subclass.unpack(reader)
-
-experimenter_stats_request.subtypes[6035143] = bsn_stats_request
-
 class bsn_lacp_stats_request(bsn_stats_request):
     version = 4
     type = 18
@@ -3386,6 +4884,100 @@
 
 bsn_stats_request.subtypes[8] = bsn_port_counter_stats_request
 
+class bsn_role_status(bsn_header):
+    version = 4
+    type = 4
+    experimenter = 6035143
+    subtype = 55
+
+    def __init__(self, xid=None, role=None, reason=None, generation_id=None):
+        if xid != None:
+            self.xid = xid
+        else:
+            self.xid = None
+        if role != None:
+            self.role = role
+        else:
+            self.role = 0
+        if reason != None:
+            self.reason = reason
+        else:
+            self.reason = 0
+        if generation_id != None:
+            self.generation_id = generation_id
+        else:
+            self.generation_id = 0
+        return
+
+    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("!L", self.role))
+        packed.append(struct.pack("!B", self.reason))
+        packed.append('\x00' * 3)
+        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(reader):
+        obj = bsn_role_status()
+        _version = reader.read("!B")[0]
+        assert(_version == 4)
+        _type = reader.read("!B")[0]
+        assert(_type == 4)
+        _length = reader.read("!H")[0]
+        orig_reader = reader
+        reader = orig_reader.slice(_length - (2 + 2))
+        obj.xid = reader.read("!L")[0]
+        _experimenter = reader.read("!L")[0]
+        assert(_experimenter == 6035143)
+        _subtype = reader.read("!L")[0]
+        assert(_subtype == 55)
+        obj.role = reader.read("!L")[0]
+        obj.reason = reader.read("!B")[0]
+        reader.skip(3)
+        obj.generation_id = reader.read("!Q")[0]
+        return obj
+
+    def __eq__(self, other):
+        if type(self) != type(other): return False
+        if self.xid != other.xid: return False
+        if self.role != other.role: return False
+        if self.reason != other.reason: return False
+        if self.generation_id != other.generation_id: return False
+        return True
+
+    def pretty_print(self, q):
+        q.text("bsn_role_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("role = ");
+                q.text("%#x" % self.role)
+                q.text(","); q.breakable()
+                q.text("reason = ");
+                q.text("%#x" % self.reason)
+                q.text(","); q.breakable()
+                q.text("generation_id = ");
+                q.text("%#x" % self.generation_id)
+            q.breakable()
+        q.text('}')
+
+bsn_header.subtypes[55] = bsn_role_status
+
 class bsn_set_lacp_reply(bsn_header):
     version = 4
     type = 4
diff --git a/src/python/loxi/of13/meter_band.py b/src/python/loxi/of13/meter_band.py
index 9c7a23f..a11c9dd 100644
--- a/src/python/loxi/of13/meter_band.py
+++ b/src/python/loxi/of13/meter_band.py
@@ -16,6 +16,7 @@
 import action_id
 import instruction_id
 import meter_band
+import bsn_tlv
 import util
 import loxi.generic_util
 
diff --git a/src/python/loxi/of13/oxm.py b/src/python/loxi/of13/oxm.py
index 2abee43..a717a33 100644
--- a/src/python/loxi/of13/oxm.py
+++ b/src/python/loxi/of13/oxm.py
@@ -16,6 +16,7 @@
 import action_id
 import instruction_id
 import meter_band
+import bsn_tlv
 import util
 import loxi.generic_util
 
diff --git a/src/python/loxi/of13/util.py b/src/python/loxi/of13/util.py
index 5958398..bf8be59 100644
--- a/src/python/loxi/of13/util.py
+++ b/src/python/loxi/of13/util.py
@@ -102,3 +102,10 @@
         except loxi.ProtocolError:
             return None
     return [x for x in loxi.generic_util.unpack_list(reader, deserializer) if x != None]
+
+def pack_checksum_128(value):
+    return struct.pack("!QQ", (value >> 64) & MASK64, value & MASK64)
+
+def unpack_checksum_128(reader):
+    hi, lo = reader.read("!QQ")
+    return (hi << 64) | lo