loxi-prep: move message parsing to ofp.message
diff --git a/src/python/of10/__init__.py b/src/python/of10/__init__.py
index 2810be8..1de296a 100644
--- a/src/python/of10/__init__.py
+++ b/src/python/of10/__init__.py
@@ -5,7 +5,7 @@
 They are checked in to simplify running OFTest.
 """
 
-__all__ = ["action_list", "action", "cstruct", "error", "message", "parse"]
+__all__ = ["action_list", "action", "cstruct", "error", "message"]
 
 # Allow accessing constants through the top-level module
 from cstruct import *
@@ -13,4 +13,3 @@
 # Allow accessing submodules without additional imports
 import action
 import message
-import parse
diff --git a/src/python/of10/message.py b/src/python/of10/message.py
index b52d40f..994e227 100644
--- a/src/python/of10/message.py
+++ b/src/python/of10/message.py
@@ -1,6 +1,7 @@
 
 # Python OpenFlow message wrapper classes
 
+import logging
 from cstruct import *
 from action_list import action_list
 from error import *
@@ -3477,3 +3478,138 @@
         _flow_mod.__init__(self, **kwargs)
         self.command = OFPFC_DELETE_STRICT
 
+# These message types are subclassed
+msg_type_subclassed = [
+    OFPT_STATS_REQUEST,
+    OFPT_STATS_REPLY,
+    OFPT_ERROR
+]
+
+# Maps from sub-types to classes
+stats_reply_to_class_map = {
+    OFPST_DESC                      : desc_stats_reply,
+    OFPST_AGGREGATE                 : aggregate_stats_reply,
+    OFPST_FLOW                      : flow_stats_reply,
+    OFPST_TABLE                     : table_stats_reply,
+    OFPST_PORT                      : port_stats_reply,
+    OFPST_QUEUE                     : queue_stats_reply
+}
+
+stats_request_to_class_map = {
+    OFPST_DESC                      : desc_stats_request,
+    OFPST_AGGREGATE                 : aggregate_stats_request,
+    OFPST_FLOW                      : flow_stats_request,
+    OFPST_TABLE                     : table_stats_request,
+    OFPST_PORT                      : port_stats_request,
+    OFPST_QUEUE                     : queue_stats_request
+}
+
+error_to_class_map = {
+    OFPET_HELLO_FAILED              : hello_failed_error_msg,
+    OFPET_BAD_REQUEST               : bad_request_error_msg,
+    OFPET_BAD_ACTION                : bad_action_error_msg,
+    OFPET_FLOW_MOD_FAILED           : flow_mod_failed_error_msg,
+    OFPET_PORT_MOD_FAILED           : port_mod_failed_error_msg,
+    OFPET_QUEUE_OP_FAILED           : queue_op_failed_error_msg
+}
+
+# Map from header type value to the underlieing message class
+msg_type_to_class_map = {
+    OFPT_HELLO                      : hello,
+    OFPT_ERROR                      : error,
+    OFPT_ECHO_REQUEST               : echo_request,
+    OFPT_ECHO_REPLY                 : echo_reply,
+    OFPT_VENDOR                     : vendor,
+    OFPT_FEATURES_REQUEST           : features_request,
+    OFPT_FEATURES_REPLY             : features_reply,
+    OFPT_GET_CONFIG_REQUEST         : get_config_request,
+    OFPT_GET_CONFIG_REPLY           : get_config_reply,
+    OFPT_SET_CONFIG                 : set_config,
+    OFPT_PACKET_IN                  : packet_in,
+    OFPT_FLOW_REMOVED               : flow_removed,
+    OFPT_PORT_STATUS                : port_status,
+    OFPT_PACKET_OUT                 : packet_out,
+    OFPT_FLOW_MOD                   : flow_mod,
+    OFPT_PORT_MOD                   : port_mod,
+    OFPT_STATS_REQUEST              : stats_request,
+    OFPT_STATS_REPLY                : stats_reply,
+    OFPT_BARRIER_REQUEST            : barrier_request,
+    OFPT_BARRIER_REPLY              : barrier_reply,
+    OFPT_QUEUE_GET_CONFIG_REQUEST   : queue_get_config_request,
+    OFPT_QUEUE_GET_CONFIG_REPLY     : queue_get_config_reply
+}
+
+def _of_message_to_object(binary_string):
+    """
+    Map a binary string to the corresponding class.
+
+    Appropriately resolves subclasses
+    """
+    hdr = ofp_header()
+    hdr.unpack(binary_string)
+    logging.info(hdr.show())
+    # FIXME: Add error detection
+    if not hdr.type in msg_type_subclassed:
+        return msg_type_to_class_map[hdr.type]()
+    if hdr.type == OFPT_STATS_REQUEST:
+        sub_hdr = ofp_stats_request()
+        sub_hdr.unpack(binary_string)
+        try:
+            obj = stats_request_to_class_map[sub_hdr.stats_type]()
+        except KeyError:
+            obj = None
+        return obj
+    elif hdr.type == OFPT_STATS_REPLY:
+        sub_hdr = ofp_stats_reply()
+        sub_hdr.unpack(binary_string)
+        try:
+            obj = stats_reply_to_class_map[sub_hdr.stats_type]()
+        except KeyError:
+            obj = None
+        return obj
+    elif hdr.type == OFPT_ERROR:
+        sub_hdr = ofp_error_msg()
+        sub_hdr.unpack(binary_string)
+        return error_to_class_map[sub_hdr.err_type]()
+    else:
+        logging.error("Cannot parse pkt to message")
+        return None
+
+def parse_message(binary_string):
+    """
+    Parse an OpenFlow packet
+
+    Parses a raw OpenFlow packet into a Python class, with class
+    members fully populated.
+
+    @param binary_string The packet (string) to be parsed
+    @param raw If true, interpret the packet as an L2 packet.  Not
+    yet supported.
+    @return An object of some message class or None if fails
+    Note that any data beyond that parsed is not returned
+
+    """
+    obj = _of_message_to_object(binary_string)
+    if obj:
+        obj.unpack(binary_string)
+    return obj
+
+
+def parse_header(binary_string):
+    """
+    Parse only the header from an OpenFlow packet
+
+    Parses the header from a raw OpenFlow packet into a
+    an ofp_header Python class.
+
+    @param binary_string The packet (string) to be parsed
+    @param raw If true, interpret the packet as an L2 packet.  Not
+    yet supported.
+    @return An ofp_header object
+
+    """
+    hdr = ofp_header()
+    hdr.unpack(binary_string)
+    return hdr
+
+
diff --git a/src/python/oftest/controller.py b/src/python/oftest/controller.py
index 944117a..88e0ffb 100644
--- a/src/python/oftest/controller.py
+++ b/src/python/oftest/controller.py
@@ -204,7 +204,7 @@
         offset = 0
         while offset < len(pkt):
             # Parse the header to get type
-            hdr = ofp.parse.of_header_parse(pkt[offset:])
+            hdr = ofp.message.parse_header(pkt[offset:])
             if not hdr or hdr.length == 0:
                 self.logger.error("Could not parse header")
                 self.logger.error("pkt len %d." % len(pkt))
@@ -233,7 +233,7 @@
                 self.disconnect()
                 return
 
-            msg = ofp.parse.of_message_parse(rawmsg)
+            msg = ofp.message.parse_message(rawmsg)
             if not msg:
                 self.parse_errors += 1
                 self.logger.warn("Could not parse message")
diff --git a/src/python/oftest/parse.py b/src/python/oftest/parse.py
index ac76a16..0005313 100644
--- a/src/python/oftest/parse.py
+++ b/src/python/oftest/parse.py
@@ -1,14 +1,10 @@
 """
-OpenFlow message parsing functions
+Utility parsing functions
 """
 
 import sys
 import logging
-import message
-import error
-import action
-import cstruct
-from action_list import action_list
+import of10 as ofp
 try:
     import scapy.all as scapy
 except:
@@ -17,161 +13,6 @@
     except:
         sys.exit("Need to install scapy for packet parsing")
 
-"""
-of_message.py
-Contains wrapper functions and classes for the of_message namespace
-that are generated by hand.  It includes the rest of the wrapper
-function information into the of_message namespace
-"""
-
-parse_logger = logging.getLogger("parse")
-#parse_logger.setLevel(logging.DEBUG)
-
-# These message types are subclassed
-msg_type_subclassed = [
-    cstruct.OFPT_STATS_REQUEST,
-    cstruct.OFPT_STATS_REPLY,
-    cstruct.OFPT_ERROR
-]
-
-# Maps from sub-types to classes
-stats_reply_to_class_map = {
-    cstruct.OFPST_DESC                      : message.desc_stats_reply,
-    cstruct.OFPST_AGGREGATE                 : message.aggregate_stats_reply,
-    cstruct.OFPST_FLOW                      : message.flow_stats_reply,
-    cstruct.OFPST_TABLE                     : message.table_stats_reply,
-    cstruct.OFPST_PORT                      : message.port_stats_reply,
-    cstruct.OFPST_QUEUE                     : message.queue_stats_reply
-}
-
-stats_request_to_class_map = {
-    cstruct.OFPST_DESC                      : message.desc_stats_request,
-    cstruct.OFPST_AGGREGATE                 : message.aggregate_stats_request,
-    cstruct.OFPST_FLOW                      : message.flow_stats_request,
-    cstruct.OFPST_TABLE                     : message.table_stats_request,
-    cstruct.OFPST_PORT                      : message.port_stats_request,
-    cstruct.OFPST_QUEUE                     : message.queue_stats_request
-}
-
-error_to_class_map = {
-    cstruct.OFPET_HELLO_FAILED              : message.hello_failed_error_msg,
-    cstruct.OFPET_BAD_REQUEST               : message.bad_request_error_msg,
-    cstruct.OFPET_BAD_ACTION                : message.bad_action_error_msg,
-    cstruct.OFPET_FLOW_MOD_FAILED           : message.flow_mod_failed_error_msg,
-    cstruct.OFPET_PORT_MOD_FAILED           : message.port_mod_failed_error_msg,
-    cstruct.OFPET_QUEUE_OP_FAILED           : message.queue_op_failed_error_msg
-}
-
-# Map from header type value to the underlieing message class
-msg_type_to_class_map = {
-    cstruct.OFPT_HELLO                      : message.hello,
-    cstruct.OFPT_ERROR                      : message.error,
-    cstruct.OFPT_ECHO_REQUEST               : message.echo_request,
-    cstruct.OFPT_ECHO_REPLY                 : message.echo_reply,
-    cstruct.OFPT_VENDOR                     : message.vendor,
-    cstruct.OFPT_FEATURES_REQUEST           : message.features_request,
-    cstruct.OFPT_FEATURES_REPLY             : message.features_reply,
-    cstruct.OFPT_GET_CONFIG_REQUEST         : message.get_config_request,
-    cstruct.OFPT_GET_CONFIG_REPLY           : message.get_config_reply,
-    cstruct.OFPT_SET_CONFIG                 : message.set_config,
-    cstruct.OFPT_PACKET_IN                  : message.packet_in,
-    cstruct.OFPT_FLOW_REMOVED               : message.flow_removed,
-    cstruct.OFPT_PORT_STATUS                : message.port_status,
-    cstruct.OFPT_PACKET_OUT                 : message.packet_out,
-    cstruct.OFPT_FLOW_MOD                   : message.flow_mod,
-    cstruct.OFPT_PORT_MOD                   : message.port_mod,
-    cstruct.OFPT_STATS_REQUEST              : message.stats_request,
-    cstruct.OFPT_STATS_REPLY                : message.stats_reply,
-    cstruct.OFPT_BARRIER_REQUEST            : message.barrier_request,
-    cstruct.OFPT_BARRIER_REPLY              : message.barrier_reply,
-    cstruct.OFPT_QUEUE_GET_CONFIG_REQUEST   : message.queue_get_config_request,
-    cstruct.OFPT_QUEUE_GET_CONFIG_REPLY     : message.queue_get_config_reply
-}
-
-def _of_message_to_object(binary_string):
-    """
-    Map a binary string to the corresponding class.
-
-    Appropriately resolves subclasses
-    """
-    hdr = message.ofp_header()
-    hdr.unpack(binary_string)
-    logging.info(hdr.show())
-    # FIXME: Add error detection
-    if not hdr.type in msg_type_subclassed:
-        return msg_type_to_class_map[hdr.type]()
-    if hdr.type == cstruct.OFPT_STATS_REQUEST:
-        sub_hdr = message.ofp_stats_request()
-        sub_hdr.unpack(binary_string)
-        try:
-            obj = stats_request_to_class_map[sub_hdr.stats_type]()
-        except KeyError:
-            obj = None
-        return obj
-    elif hdr.type == cstruct.OFPT_STATS_REPLY:
-        sub_hdr = message.ofp_stats_reply()
-        sub_hdr.unpack(binary_string)
-        try:
-            obj = stats_reply_to_class_map[sub_hdr.stats_type]()
-        except KeyError:
-            obj = None
-        return obj
-    elif hdr.type == cstruct.OFPT_ERROR:
-        sub_hdr = message.ofp_error_msg()
-        sub_hdr.unpack(binary_string)
-        return error_to_class_map[sub_hdr.err_type]()
-    else:
-        parse_logger.error("Cannot parse pkt to message")
-        return None
-
-def of_message_parse(binary_string, raw=False):
-    """
-    Parse an OpenFlow packet
-
-    Parses a raw OpenFlow packet into a Python class, with class
-    members fully populated.
-
-    @param binary_string The packet (string) to be parsed
-    @param raw If true, interpret the packet as an L2 packet.  Not
-    yet supported.
-    @return An object of some message class or None if fails
-    Note that any data beyond that parsed is not returned
-
-    """
-
-    if raw:
-        parse_logger.error("raw packet message parsing not supported")
-        return None
-
-    obj = _of_message_to_object(binary_string)
-    if obj:
-        obj.unpack(binary_string)
-    return obj
-
-
-def of_header_parse(binary_string, raw=False):
-    """
-    Parse only the header from an OpenFlow packet
-
-    Parses the header from a raw OpenFlow packet into a
-    an ofp_header Python class.
-
-    @param binary_string The packet (string) to be parsed
-    @param raw If true, interpret the packet as an L2 packet.  Not
-    yet supported.
-    @return An ofp_header object
-
-    """
-
-    if raw:
-        parse_logger.error("raw packet message parsing not supported")
-        return None
-
-    hdr = message.ofp_header()
-    hdr.unpack(binary_string)
-
-    return hdr
-
 map_wc_field_to_match_member = {
     'OFPFW_DL_VLAN'                 : 'vlan_vid',
     'OFPFW_DL_SRC'                  : 'eth_src',
@@ -270,7 +111,7 @@
 
     #@todo check min length of packet
     if pkt_format.upper() != "L2":
-        parse_logger.error("Only L2 supported for packet_to_flow")
+        logging.error("Only L2 supported for packet_to_flow")
         return None
 
     if type(packet) == type(""):
@@ -282,63 +123,63 @@
     try:
         (dot1q, ip, tcp, udp, icmp, arp) = packet_type_classify(ether)
     except:
-        parse_logger.error("packet_to_flow_match: Classify error")
+        logging.error("packet_to_flow_match: Classify error")
         return None
 
-    match = cstruct.ofp_match()
-    match.wildcards = cstruct.OFPFW_ALL
+    match = ofp.ofp_match()
+    match.wildcards = ofp.OFPFW_ALL
     #@todo Check if packet is other than L2 format
     match.eth_dst = parse_mac(ether.dst)
-    match.wildcards &= ~cstruct.OFPFW_DL_DST
+    match.wildcards &= ~ofp.OFPFW_DL_DST
     match.eth_src = parse_mac(ether.src)
-    match.wildcards &= ~cstruct.OFPFW_DL_SRC
+    match.wildcards &= ~ofp.OFPFW_DL_SRC
     match.eth_type = ether.type
-    match.wildcards &= ~cstruct.OFPFW_DL_TYPE
+    match.wildcards &= ~ofp.OFPFW_DL_TYPE
 
     if dot1q:
         match.vlan_vid = dot1q.vlan
         match.vlan_pcp = dot1q.prio
         match.eth_type = dot1q.type
     else:
-        match.vlan_vid = cstruct.OFP_VLAN_NONE
+        match.vlan_vid = ofp.OFP_VLAN_NONE
         match.vlan_pcp = 0
-    match.wildcards &= ~cstruct.OFPFW_DL_VLAN
-    match.wildcards &= ~cstruct.OFPFW_DL_VLAN_PCP
+    match.wildcards &= ~ofp.OFPFW_DL_VLAN
+    match.wildcards &= ~ofp.OFPFW_DL_VLAN_PCP
 
     if ip:
         match.ipv4_src = parse_ip(ip.src)
-        match.wildcards &= ~cstruct.OFPFW_NW_SRC_MASK
+        match.wildcards &= ~ofp.OFPFW_NW_SRC_MASK
         match.ipv4_dst = parse_ip(ip.dst)
-        match.wildcards &= ~cstruct.OFPFW_NW_DST_MASK
+        match.wildcards &= ~ofp.OFPFW_NW_DST_MASK
         match.ip_dscp = ip.tos
-        match.wildcards &= ~cstruct.OFPFW_NW_TOS
+        match.wildcards &= ~ofp.OFPFW_NW_TOS
 
     if tcp:
         match.ip_proto = 6
-        match.wildcards &= ~cstruct.OFPFW_NW_PROTO
+        match.wildcards &= ~ofp.OFPFW_NW_PROTO
     elif not tcp and udp:
         tcp = udp
         match.ip_proto = 17
-        match.wildcards &= ~cstruct.OFPFW_NW_PROTO
+        match.wildcards &= ~ofp.OFPFW_NW_PROTO
 
     if tcp:
         match.tcp_src = tcp.sport
-        match.wildcards &= ~cstruct.OFPFW_TP_SRC
+        match.wildcards &= ~ofp.OFPFW_TP_SRC
         match.tcp_dst = tcp.dport
-        match.wildcards &= ~cstruct.OFPFW_TP_DST
+        match.wildcards &= ~ofp.OFPFW_TP_DST
 
     if icmp:
         match.ip_proto = 1
         match.tcp_src = icmp.type
         match.tcp_dst = icmp.code
-        match.wildcards &= ~cstruct.OFPFW_NW_PROTO
+        match.wildcards &= ~ofp.OFPFW_NW_PROTO
 
     if arp:
         match.ip_proto = arp.op
-        match.wildcards &= ~cstruct.OFPFW_NW_PROTO
+        match.wildcards &= ~ofp.OFPFW_NW_PROTO
         match.ipv4_src = parse_ip(arp.psrc)
-        match.wildcards &= ~cstruct.OFPFW_NW_SRC_MASK
+        match.wildcards &= ~ofp.OFPFW_NW_SRC_MASK
         match.ipv4_dst = parse_ip(arp.pdst)
-        match.wildcards &= ~cstruct.OFPFW_NW_DST_MASK
+        match.wildcards &= ~ofp.OFPFW_NW_DST_MASK
 
     return match
diff --git a/src/python/oftest/testutils.py b/src/python/oftest/testutils.py
index a1db2e0..6e29dc3 100644
--- a/src/python/oftest/testutils.py
+++ b/src/python/oftest/testutils.py
@@ -19,7 +19,7 @@
 import of10
 import of10.message
 import of10.action
-import of10.parse
+import oftest.parse
 
 global skipped_test_count
 skipped_test_count = 0
@@ -544,7 +544,7 @@
                                " != " + str(res_match.tcp_dst))
 
 def packet_to_flow_match(parent, packet):
-    match = of10.parse.packet_to_flow_match(packet)
+    match = oftest.parse.packet_to_flow_match(packet)
     match.wildcards |= required_wildcards(parent)
     return match
 
@@ -559,7 +559,7 @@
     @param in_band if True, do not wildcard ingress port
     @param egr_ports None (drop), single port or list of ports
     """
-    match = of10.parse.packet_to_flow_match(pkt)
+    match = oftest.parse.packet_to_flow_match(pkt)
     parent.assertTrue(match is not None, "Flow match from pkt failed")
     if wildcards is None:
         wildcards = required_wildcards(parent)
@@ -817,10 +817,10 @@
 
     if field_to_mod == 'eth_dst':
         act = of10.action.action_set_dl_dst()
-        act.dl_addr = of10.parse.parse_mac(mod_field_vals['eth_dst'])
+        act.dl_addr = oftest.parse.parse_mac(mod_field_vals['eth_dst'])
     elif field_to_mod == 'eth_src':
         act = of10.action.action_set_dl_src()
-        act.dl_addr = of10.parse.parse_mac(mod_field_vals['eth_src'])
+        act.dl_addr = oftest.parse.parse_mac(mod_field_vals['eth_src'])
     elif field_to_mod == 'dl_vlan_enable':
         if not mod_field_vals['dl_vlan_enable']: # Strip VLAN tag
             act = of10.action.action_strip_vlan()
@@ -834,10 +834,10 @@
         act.vlan_pcp = mod_field_vals['vlan_pcp']
     elif field_to_mod == 'ip_src':
         act = of10.action.action_set_nw_src()
-        act.nw_addr = of10.parse.parse_ip(mod_field_vals['ip_src'])
+        act.nw_addr = oftest.parse.parse_ip(mod_field_vals['ip_src'])
     elif field_to_mod == 'ip_dst':
         act = of10.action.action_set_nw_dst()
-        act.nw_addr = of10.parse.parse_ip(mod_field_vals['ip_dst'])
+        act.nw_addr = oftest.parse.parse_ip(mod_field_vals['ip_dst'])
     elif field_to_mod == 'ip_tos':
         act = of10.action.action_set_nw_tos()
         act.nw_tos = mod_field_vals['ip_tos']
diff --git a/tools/munger/scripts/message_gen.py b/tools/munger/scripts/message_gen.py
index 3e39bdf..b59c42e 100644
--- a/tools/munger/scripts/message_gen.py
+++ b/tools/munger/scripts/message_gen.py
@@ -87,6 +87,7 @@
 message_top_matter = """
 # Python OpenFlow message wrapper classes
 
+import logging
 from cstruct import *
 from action_list import action_list
 from error import *
@@ -834,6 +835,141 @@
     def __init__(self, **kwargs):
         _flow_mod.__init__(self, **kwargs)
         self.command = OFPFC_DELETE_STRICT
+
+# These message types are subclassed
+msg_type_subclassed = [
+    OFPT_STATS_REQUEST,
+    OFPT_STATS_REPLY,
+    OFPT_ERROR
+]
+
+# Maps from sub-types to classes
+stats_reply_to_class_map = {
+    OFPST_DESC                      : desc_stats_reply,
+    OFPST_AGGREGATE                 : aggregate_stats_reply,
+    OFPST_FLOW                      : flow_stats_reply,
+    OFPST_TABLE                     : table_stats_reply,
+    OFPST_PORT                      : port_stats_reply,
+    OFPST_QUEUE                     : queue_stats_reply
+}
+
+stats_request_to_class_map = {
+    OFPST_DESC                      : desc_stats_request,
+    OFPST_AGGREGATE                 : aggregate_stats_request,
+    OFPST_FLOW                      : flow_stats_request,
+    OFPST_TABLE                     : table_stats_request,
+    OFPST_PORT                      : port_stats_request,
+    OFPST_QUEUE                     : queue_stats_request
+}
+
+error_to_class_map = {
+    OFPET_HELLO_FAILED              : hello_failed_error_msg,
+    OFPET_BAD_REQUEST               : bad_request_error_msg,
+    OFPET_BAD_ACTION                : bad_action_error_msg,
+    OFPET_FLOW_MOD_FAILED           : flow_mod_failed_error_msg,
+    OFPET_PORT_MOD_FAILED           : port_mod_failed_error_msg,
+    OFPET_QUEUE_OP_FAILED           : queue_op_failed_error_msg
+}
+
+# Map from header type value to the underlieing message class
+msg_type_to_class_map = {
+    OFPT_HELLO                      : hello,
+    OFPT_ERROR                      : error,
+    OFPT_ECHO_REQUEST               : echo_request,
+    OFPT_ECHO_REPLY                 : echo_reply,
+    OFPT_VENDOR                     : vendor,
+    OFPT_FEATURES_REQUEST           : features_request,
+    OFPT_FEATURES_REPLY             : features_reply,
+    OFPT_GET_CONFIG_REQUEST         : get_config_request,
+    OFPT_GET_CONFIG_REPLY           : get_config_reply,
+    OFPT_SET_CONFIG                 : set_config,
+    OFPT_PACKET_IN                  : packet_in,
+    OFPT_FLOW_REMOVED               : flow_removed,
+    OFPT_PORT_STATUS                : port_status,
+    OFPT_PACKET_OUT                 : packet_out,
+    OFPT_FLOW_MOD                   : flow_mod,
+    OFPT_PORT_MOD                   : port_mod,
+    OFPT_STATS_REQUEST              : stats_request,
+    OFPT_STATS_REPLY                : stats_reply,
+    OFPT_BARRIER_REQUEST            : barrier_request,
+    OFPT_BARRIER_REPLY              : barrier_reply,
+    OFPT_QUEUE_GET_CONFIG_REQUEST   : queue_get_config_request,
+    OFPT_QUEUE_GET_CONFIG_REPLY     : queue_get_config_reply
+}
+
+def _of_message_to_object(binary_string):
+    \"""
+    Map a binary string to the corresponding class.
+
+    Appropriately resolves subclasses
+    \"""
+    hdr = ofp_header()
+    hdr.unpack(binary_string)
+    logging.info(hdr.show())
+    # FIXME: Add error detection
+    if not hdr.type in msg_type_subclassed:
+        return msg_type_to_class_map[hdr.type]()
+    if hdr.type == OFPT_STATS_REQUEST:
+        sub_hdr = ofp_stats_request()
+        sub_hdr.unpack(binary_string)
+        try:
+            obj = stats_request_to_class_map[sub_hdr.stats_type]()
+        except KeyError:
+            obj = None
+        return obj
+    elif hdr.type == OFPT_STATS_REPLY:
+        sub_hdr = ofp_stats_reply()
+        sub_hdr.unpack(binary_string)
+        try:
+            obj = stats_reply_to_class_map[sub_hdr.stats_type]()
+        except KeyError:
+            obj = None
+        return obj
+    elif hdr.type == OFPT_ERROR:
+        sub_hdr = ofp_error_msg()
+        sub_hdr.unpack(binary_string)
+        return error_to_class_map[sub_hdr.err_type]()
+    else:
+        logging.error("Cannot parse pkt to message")
+        return None
+
+def parse_message(binary_string):
+    \"""
+    Parse an OpenFlow packet
+
+    Parses a raw OpenFlow packet into a Python class, with class
+    members fully populated.
+
+    @param binary_string The packet (string) to be parsed
+    @param raw If true, interpret the packet as an L2 packet.  Not
+    yet supported.
+    @return An object of some message class or None if fails
+    Note that any data beyond that parsed is not returned
+
+    \"""
+    obj = _of_message_to_object(binary_string)
+    if obj:
+        obj.unpack(binary_string)
+    return obj
+
+
+def parse_header(binary_string):
+    \"""
+    Parse only the header from an OpenFlow packet
+
+    Parses the header from a raw OpenFlow packet into a
+    an ofp_header Python class.
+
+    @param binary_string The packet (string) to be parsed
+    @param raw If true, interpret the packet as an L2 packet.  Not
+    yet supported.
+    @return An ofp_header object
+
+    \"""
+    hdr = ofp_header()
+    hdr.unpack(binary_string)
+    return hdr
+
 """
 
 #