pyloxi: support hello_elems
diff --git a/py_gen/codegen.py b/py_gen/codegen.py
index 19bdbaf..9765815 100644
--- a/py_gen/codegen.py
+++ b/py_gen/codegen.py
@@ -68,6 +68,8 @@
             type_values['subtype'] = type_maps.extension_action_to_subtype(cls, version)
     elif utils.class_is_queue_prop(cls):
         type_values['type'] = util.constant_for_value(version, "ofp_queue_properties", util.primary_wire_type(cls, version))
+    elif utils.class_is_hello_elem(cls):
+        type_values['type'] = util.constant_for_value(version, "ofp_hello_elem_type", util.primary_wire_type(cls, version))
     elif utils.class_is_oxm(cls):
         oxm_class = 0x8000
         oxm_type = util.primary_wire_type(cls, version)
@@ -82,7 +84,8 @@
 def build_ofclasses(version):
     blacklist = ["of_action", "of_action_header", "of_header", "of_queue_prop",
                  "of_queue_prop_header", "of_experimenter", "of_action_experimenter",
-                 "of_oxm", "of_oxm_header", "of_oxm_experimenter_header"]
+                 "of_oxm", "of_oxm_header", "of_oxm_experimenter_header",
+                 "of_hello_elem", "of_hello_elem_header"]
     ofclasses = []
     for cls in of_g.standard_class_order:
         if version not in of_g.unified[cls] or cls in blacklist:
diff --git a/py_gen/oftype.py b/py_gen/oftype.py
index a52bd2e..481321c 100644
--- a/py_gen/oftype.py
+++ b/py_gen/oftype.py
@@ -122,6 +122,8 @@
             return 'common.unpack_list_queue_prop(buffer(%s, %s))' % (buf_expr, offset_expr)
         elif self.base == 'of_list_packet_queue_t':
             return 'common.unpack_list_packet_queue(buffer(%s, %s))' % (buf_expr, offset_expr)
+        elif self.base == 'of_list_hello_elem_t':
+            return 'common.unpack_list_hello_elem(buffer(%s, %s))' % (buf_expr, offset_expr)
         elif self.base == 'of_port_name_t':
             return self._gen_string_unpack_expr(16, buf_expr, offset_expr)
         elif self.base == 'of_table_name_t' or self.base == 'of_serial_num_t':
diff --git a/py_gen/templates/common.py b/py_gen/templates/common.py
index 99d3f71..2f9310e 100644
--- a/py_gen/templates/common.py
+++ b/py_gen/templates/common.py
@@ -53,6 +53,15 @@
 def unpack_list_packet_queue(buf):
     return util.unpack_list(packet_queue.unpack, "!4xH", buf)
 
+def unpack_list_hello_elem(buf):
+    def deserializer(buf):
+        type, = struct.unpack_from("!H", buf)
+        if type == const.OFPHET_VERSIONBITMAP:
+            return hello_elem_versionbitmap.unpack(buf)
+        else:
+            return None
+    return [x for x in util.unpack_list(deserializer, "!2xH", buf) if x != None]
+
 :: for ofclass in ofclasses:
 :: include('_ofclass.py', ofclass=ofclass, superclass="object")
 
diff --git a/py_gen/tests/of13.py b/py_gen/tests/of13.py
index 0294684..68cbb1a 100644
--- a/py_gen/tests/of13.py
+++ b/py_gen/tests/of13.py
@@ -53,6 +53,35 @@
         self.assertTrue(hasattr(loxi.of13, "const"))
         self.assertTrue(hasattr(loxi.of13, "message"))
 
+class TestCommon(unittest.TestCase):
+    sample_hello_elem_buf = ''.join([
+        '\x00\x01', # type
+        '\x00\x0c', # length
+        '\x01\x23\x45\x67', # bitmaps[0]
+        '\x89\xab\xcd\xef', # bitmaps[1]
+    ])
+
+    def test_hello_elem_versionbitmap_pack(self):
+        obj = ofp.hello_elem_versionbitmap(bitmaps=[ofp.uint32(0x01234567),ofp.uint32(0x89abcdef)])
+        self.assertEquals(self.sample_hello_elem_buf, obj.pack())
+
+    def test_hello_elem_versionbitmap_unpack(self):
+        obj = ofp.hello_elem_versionbitmap.unpack(self.sample_hello_elem_buf)
+        self.assertEquals(len(obj.bitmaps), 2)
+        self.assertEquals(obj.bitmaps[0], ofp.uint32(0x01234567))
+        self.assertEquals(obj.bitmaps[1], ofp.uint32(0x89abcdef))
+
+    def test_list_hello_elem_unpack(self):
+        buf = ''.join([
+            '\x00\x01\x00\x04', # versionbitmap
+            '\x00\x00\x00\x04', # unknown type
+            '\x00\x01\x00\x04', # versionbitmap
+        ])
+        l = ofp.unpack_list_hello_elem(buf)
+        self.assertEquals(len(l), 2)
+        self.assertTrue(isinstance(l[0], ofp.hello_elem_versionbitmap))
+        self.assertTrue(isinstance(l[1], ofp.hello_elem_versionbitmap))
+
 class TestOXM(unittest.TestCase):
     def test_oxm_in_phy_port_pack(self):
         import loxi.of13 as ofp
@@ -128,9 +157,6 @@
             ofp.common.action_id_set_queue,
             ofp.common.flow_stats_entry,
             ofp.common.group_desc_stats_entry,
-            ofp.common.hello_elem,
-            ofp.common.hello_elem_header,
-            ofp.common.hello_elem_versionbitmap,
             ofp.common.instruction,
             ofp.common.instruction_apply_actions,
             ofp.common.instruction_clear_actions,
@@ -218,9 +244,6 @@
             ofp.common.action_id_set_queue,
             ofp.common.flow_stats_entry,
             ofp.common.group_desc_stats_entry,
-            ofp.common.hello_elem,
-            ofp.common.hello_elem_header,
-            ofp.common.hello_elem_versionbitmap,
             ofp.common.instruction,
             ofp.common.instruction_apply_actions,
             ofp.common.instruction_clear_actions,