update pyloxi to c47bc6facb2869a7833b8694b7a20b3113284d94
diff --git a/src/python/loxi/generic_util.py b/src/python/loxi/generic_util.py
index ce31049..f965e64 100644
--- a/src/python/loxi/generic_util.py
+++ b/src/python/loxi/generic_util.py
@@ -40,6 +40,13 @@
         return deserializer(reader.slice(length), typ)
     return unpack_list(reader, wrapper)
 
+def pad_to(alignment, length):
+    """
+    Return a string of zero bytes that will pad a string of length 'length' to
+    a multiple of 'alignment'.
+    """
+    return "\x00" * ((length + alignment - 1)/alignment*alignment - length)
+
 class OFReader(object):
     """
     Cursor over a read-only buffer
@@ -79,6 +86,12 @@
             raise loxi.ProtocolError("Buffer too short")
         self.offset += length
 
+    def skip_align(self):
+        new_offset = (self.offset + 7) / 8 * 8
+        if new_offset > len(self.buf):
+            raise loxi.ProtocolError("Buffer too short")
+        self.offset = new_offset
+
     def is_empty(self):
         return self.offset == len(self.buf)
 
diff --git a/src/python/loxi/of10/const.py b/src/python/loxi/of10/const.py
index 1d29975..dc768c6 100644
--- a/src/python/loxi/of10/const.py
+++ b/src/python/loxi/of10/const.py
@@ -111,6 +111,15 @@
     65535: 'OF_BSN_VPORT_Q_IN_Q_UNTAGGED',
 }
 
+# Identifiers from group ofp_bsn_vport_status
+OF_BSN_VPORT_STATUS_OK = 0
+OF_BSN_VPORT_STATUS_FAILED = 1
+
+ofp_bsn_vport_status_map = {
+    0: 'OF_BSN_VPORT_STATUS_OK',
+    1: 'OF_BSN_VPORT_STATUS_FAILED',
+}
+
 # Identifiers from group ofp_capabilities
 OFPC_FLOW_STATS = 1
 OFPC_TABLE_STATS = 2
diff --git a/src/python/loxi/of11/const.py b/src/python/loxi/of11/const.py
index bd0fd11..4360d37 100644
--- a/src/python/loxi/of11/const.py
+++ b/src/python/loxi/of11/const.py
@@ -186,6 +186,15 @@
     65535: 'OF_BSN_VPORT_Q_IN_Q_UNTAGGED',
 }
 
+# Identifiers from group ofp_bsn_vport_status
+OF_BSN_VPORT_STATUS_OK = 0
+OF_BSN_VPORT_STATUS_FAILED = 1
+
+ofp_bsn_vport_status_map = {
+    0: 'OF_BSN_VPORT_STATUS_OK',
+    1: 'OF_BSN_VPORT_STATUS_FAILED',
+}
+
 # Identifiers from group ofp_capabilities
 OFPC_FLOW_STATS = 1
 OFPC_TABLE_STATS = 2
diff --git a/src/python/loxi/of12/action.py b/src/python/loxi/of12/action.py
index f1f9272..9ae3d8f 100644
--- a/src/python/loxi/of12/action.py
+++ b/src/python/loxi/of12/action.py
@@ -11,6 +11,7 @@
 import util
 import loxi.generic_util
 import loxi
+import oxm # for unpack
 
 def unpack_list(reader):
     def deserializer(reader, typ):
@@ -756,15 +757,17 @@
         if field != None:
             self.field = field
         else:
-            self.field = ''
+            self.field = None
         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)
+        packed.append(self.field.pack())
         length = sum([len(x) for x in packed])
+        packed.append(loxi.generic_util.pad_to(8, length))
+        length += len(packed[-1])
         packed[1] = struct.pack("!H", length)
         return ''.join(packed)
 
@@ -778,7 +781,8 @@
         _type = reader.read("!H")[0]
         assert(_type == 25)
         _len = reader.read("!H")[0]
-        obj.field = str(reader.read_all())
+        obj.field = oxm.unpack(reader)
+        reader.skip_align()
         return obj
 
     def __eq__(self, other):
diff --git a/src/python/loxi/of12/common.py b/src/python/loxi/of12/common.py
index f2d2493..698fe7a 100644
--- a/src/python/loxi/of12/common.py
+++ b/src/python/loxi/of12/common.py
@@ -706,7 +706,7 @@
         packed.append(util.pack_list(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))
+        packed.append(loxi.generic_util.pad_to(8, length))
         return ''.join(packed)
 
     @staticmethod
@@ -720,7 +720,7 @@
         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)
+        reader.skip_align()
         return obj
 
     def __eq__(self, other):
diff --git a/src/python/loxi/of12/const.py b/src/python/loxi/of12/const.py
index 20f99bb..b654b1a 100644
--- a/src/python/loxi/of12/const.py
+++ b/src/python/loxi/of12/const.py
@@ -187,6 +187,15 @@
     65535: 'OF_BSN_VPORT_Q_IN_Q_UNTAGGED',
 }
 
+# Identifiers from group ofp_bsn_vport_status
+OF_BSN_VPORT_STATUS_OK = 0
+OF_BSN_VPORT_STATUS_FAILED = 1
+
+ofp_bsn_vport_status_map = {
+    0: 'OF_BSN_VPORT_STATUS_OK',
+    1: 'OF_BSN_VPORT_STATUS_FAILED',
+}
+
 # Identifiers from group ofp_capabilities
 OFPC_FLOW_STATS = 1
 OFPC_TABLE_STATS = 2
diff --git a/src/python/loxi/of12/oxm.py b/src/python/loxi/of12/oxm.py
index f17151e..0fd7948 100644
--- a/src/python/loxi/of12/oxm.py
+++ b/src/python/loxi/of12/oxm.py
@@ -12,15 +12,16 @@
 import loxi.generic_util
 import loxi
 
+def unpack(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))
+
 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)
+    return loxi.generic_util.unpack_list(reader, unpack)
 
 class OXM(object):
     type_len = None # override in subclass
@@ -1907,7 +1908,7 @@
             with q.indent(2):
                 q.breakable()
                 q.text("value = ");
-                q.text("%#x" % self.value)
+                q.text(util.pretty_ipv4(self.value))
             q.breakable()
         q.text('}')
 
@@ -1963,10 +1964,10 @@
             with q.indent(2):
                 q.breakable()
                 q.text("value = ");
-                q.text("%#x" % self.value)
+                q.text(util.pretty_ipv4(self.value))
                 q.text(","); q.breakable()
                 q.text("value_mask = ");
-                q.text("%#x" % self.value_mask)
+                q.text(util.pretty_ipv4(self.value_mask))
             q.breakable()
         q.text('}')
 
@@ -2015,7 +2016,7 @@
             with q.indent(2):
                 q.breakable()
                 q.text("value = ");
-                q.text("%#x" % self.value)
+                q.text(util.pretty_ipv4(self.value))
             q.breakable()
         q.text('}')
 
@@ -2071,10 +2072,10 @@
             with q.indent(2):
                 q.breakable()
                 q.text("value = ");
-                q.text("%#x" % self.value)
+                q.text(util.pretty_ipv4(self.value))
                 q.text(","); q.breakable()
                 q.text("value_mask = ");
-                q.text("%#x" % self.value_mask)
+                q.text(util.pretty_ipv4(self.value_mask))
             q.breakable()
         q.text('}')
 
diff --git a/src/python/loxi/of13/action.py b/src/python/loxi/of13/action.py
index 645916a..a1e7877 100644
--- a/src/python/loxi/of13/action.py
+++ b/src/python/loxi/of13/action.py
@@ -11,6 +11,7 @@
 import util
 import loxi.generic_util
 import loxi
+import oxm # for unpack
 
 def unpack_list(reader):
     def deserializer(reader, typ):
@@ -859,15 +860,17 @@
         if field != None:
             self.field = field
         else:
-            self.field = ''
+            self.field = None
         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)
+        packed.append(self.field.pack())
         length = sum([len(x) for x in packed])
+        packed.append(loxi.generic_util.pad_to(8, length))
+        length += len(packed[-1])
         packed[1] = struct.pack("!H", length)
         return ''.join(packed)
 
@@ -881,7 +884,8 @@
         _type = reader.read("!H")[0]
         assert(_type == 25)
         _len = reader.read("!H")[0]
-        obj.field = str(reader.read_all())
+        obj.field = oxm.unpack(reader)
+        reader.skip_align()
         return obj
 
     def __eq__(self, other):
diff --git a/src/python/loxi/of13/common.py b/src/python/loxi/of13/common.py
index e3f9921..952aeba 100644
--- a/src/python/loxi/of13/common.py
+++ b/src/python/loxi/of13/common.py
@@ -781,7 +781,7 @@
         packed.append(util.pack_list(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))
+        packed.append(loxi.generic_util.pad_to(8, length))
         return ''.join(packed)
 
     @staticmethod
@@ -795,7 +795,7 @@
         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)
+        reader.skip_align()
         return obj
 
     def __eq__(self, other):
diff --git a/src/python/loxi/of13/const.py b/src/python/loxi/of13/const.py
index e2545f1..648617f 100644
--- a/src/python/loxi/of13/const.py
+++ b/src/python/loxi/of13/const.py
@@ -193,6 +193,15 @@
     65535: 'OF_BSN_VPORT_Q_IN_Q_UNTAGGED',
 }
 
+# Identifiers from group ofp_bsn_vport_status
+OF_BSN_VPORT_STATUS_OK = 0
+OF_BSN_VPORT_STATUS_FAILED = 1
+
+ofp_bsn_vport_status_map = {
+    0: 'OF_BSN_VPORT_STATUS_OK',
+    1: 'OF_BSN_VPORT_STATUS_FAILED',
+}
+
 # Identifiers from group ofp_capabilities
 OFPC_FLOW_STATS = 1
 OFPC_TABLE_STATS = 2
diff --git a/src/python/loxi/of13/oxm.py b/src/python/loxi/of13/oxm.py
index f17151e..0fd7948 100644
--- a/src/python/loxi/of13/oxm.py
+++ b/src/python/loxi/of13/oxm.py
@@ -12,15 +12,16 @@
 import loxi.generic_util
 import loxi
 
+def unpack(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))
+
 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)
+    return loxi.generic_util.unpack_list(reader, unpack)
 
 class OXM(object):
     type_len = None # override in subclass
@@ -1907,7 +1908,7 @@
             with q.indent(2):
                 q.breakable()
                 q.text("value = ");
-                q.text("%#x" % self.value)
+                q.text(util.pretty_ipv4(self.value))
             q.breakable()
         q.text('}')
 
@@ -1963,10 +1964,10 @@
             with q.indent(2):
                 q.breakable()
                 q.text("value = ");
-                q.text("%#x" % self.value)
+                q.text(util.pretty_ipv4(self.value))
                 q.text(","); q.breakable()
                 q.text("value_mask = ");
-                q.text("%#x" % self.value_mask)
+                q.text(util.pretty_ipv4(self.value_mask))
             q.breakable()
         q.text('}')
 
@@ -2015,7 +2016,7 @@
             with q.indent(2):
                 q.breakable()
                 q.text("value = ");
-                q.text("%#x" % self.value)
+                q.text(util.pretty_ipv4(self.value))
             q.breakable()
         q.text('}')
 
@@ -2071,10 +2072,10 @@
             with q.indent(2):
                 q.breakable()
                 q.text("value = ");
-                q.text("%#x" % self.value)
+                q.text(util.pretty_ipv4(self.value))
                 q.text(","); q.breakable()
                 q.text("value_mask = ");
-                q.text("%#x" % self.value_mask)
+                q.text(util.pretty_ipv4(self.value_mask))
             q.breakable()
         q.text('}')