copy in of11 package

These modules were copied from the oft-1.1 branch.
diff --git a/src/python/of11/parse.py b/src/python/of11/parse.py
new file mode 100644
index 0000000..dfe24c6
--- /dev/null
+++ b/src/python/of11/parse.py
@@ -0,0 +1,231 @@
+"""
+OpenFlow message parsing functions
+"""
+
+import logging
+import message
+import cstruct as ofp
+
+"""
+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 = [
+    ofp.OFPT_STATS_REQUEST,
+    ofp.OFPT_STATS_REPLY,
+    ofp.OFPT_ERROR
+]
+
+# Maps from sub-types to classes
+stats_reply_to_class_map = {
+    ofp.OFPST_DESC                      : message.desc_stats_reply,
+    ofp.OFPST_AGGREGATE                 : message.aggregate_stats_reply,
+    ofp.OFPST_FLOW                      : message.flow_stats_reply,
+    ofp.OFPST_TABLE                     : message.table_stats_reply,
+    ofp.OFPST_PORT                      : message.port_stats_reply,
+    ofp.OFPST_QUEUE                     : message.queue_stats_reply
+}
+
+stats_request_to_class_map = {
+    ofp.OFPST_DESC                      : message.desc_stats_request,
+    ofp.OFPST_AGGREGATE                 : message.aggregate_stats_request,
+    ofp.OFPST_FLOW                      : message.flow_stats_request,
+    ofp.OFPST_TABLE                     : message.table_stats_request,
+    ofp.OFPST_PORT                      : message.port_stats_request,
+    ofp.OFPST_QUEUE                     : message.queue_stats_request
+}
+
+error_to_class_map = {
+    ofp.OFPET_HELLO_FAILED              : message.hello_failed_error_msg,
+    ofp.OFPET_BAD_REQUEST               : message.bad_request_error_msg,
+    ofp.OFPET_BAD_ACTION                : message.bad_action_error_msg,
+    ofp.OFPET_FLOW_MOD_FAILED           : message.flow_mod_failed_error_msg,
+    ofp.OFPET_PORT_MOD_FAILED           : message.port_mod_failed_error_msg,
+    ofp.OFPET_QUEUE_OP_FAILED           : message.queue_op_failed_error_msg,
+    ofp.OFPET_TABLE_MOD_FAILED          : message.table_mod_failed_error_msg,
+    ofp.OFPET_QUEUE_OP_FAILED           : message.queue_op_failed_error_msg,
+    ofp.OFPET_SWITCH_CONFIG_FAILED      : message.switch_config_failed_error_msg
+}
+
+# Map from header type value to the underlieing message class
+msg_type_to_class_map = {
+    ofp.OFPT_HELLO                      : message.hello,
+    ofp.OFPT_ERROR                      : message.error,
+    ofp.OFPT_ECHO_REQUEST               : message.echo_request,
+    ofp.OFPT_ECHO_REPLY                 : message.echo_reply,
+    ofp.OFPT_EXPERIMENTER               : message.experimenter,
+    ofp.OFPT_FEATURES_REQUEST           : message.features_request,
+    ofp.OFPT_FEATURES_REPLY             : message.features_reply,
+    ofp.OFPT_GET_CONFIG_REQUEST         : message.get_config_request,
+    ofp.OFPT_GET_CONFIG_REPLY           : message.get_config_reply,
+    ofp.OFPT_SET_CONFIG                 : message.set_config,
+    ofp.OFPT_PACKET_IN                  : message.packet_in,
+    ofp.OFPT_FLOW_REMOVED               : message.flow_removed,
+    ofp.OFPT_PORT_STATUS                : message.port_status,
+    ofp.OFPT_PACKET_OUT                 : message.packet_out,
+    ofp.OFPT_FLOW_MOD                   : message.flow_mod,
+    ofp.OFPT_PORT_MOD                   : message.port_mod,
+    ofp.OFPT_TABLE_MOD                  : message.table_mod,
+    ofp.OFPT_STATS_REQUEST              : message.stats_request,
+    ofp.OFPT_STATS_REPLY                : message.stats_reply,
+    ofp.OFPT_BARRIER_REQUEST            : message.barrier_request,
+    ofp.OFPT_BARRIER_REPLY              : message.barrier_reply,
+    ofp.OFPT_QUEUE_GET_CONFIG_REQUEST   : message.queue_get_config_request,
+    ofp.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 = ofp.ofp_header()
+    hdr.unpack(binary_string)
+    # FIXME: Add error detection
+    if not hdr.type in msg_type_subclassed:
+        return msg_type_to_class_map[hdr.type]()
+    if hdr.type == ofp.OFPT_STATS_REQUEST:
+        sub_hdr = ofp.ofp_stats_request()
+        sub_hdr.unpack(binary_string[ofp.OFP_HEADER_BYTES:])
+        try:
+            obj = stats_request_to_class_map[sub_hdr.type]()
+        except LookupError:
+            obj = None
+        return obj
+    elif hdr.type == ofp.OFPT_STATS_REPLY:
+        sub_hdr = ofp.ofp_stats_reply()
+        sub_hdr.unpack(binary_string[ofp.OFP_HEADER_BYTES:])
+        try:
+            obj = stats_reply_to_class_map[sub_hdr.type]()
+        except LookupError:
+            obj = None
+        return obj
+    elif hdr.type == ofp.OFPT_ERROR:
+        sub_hdr = ofp.ofp_error_msg()
+        sub_hdr.unpack(binary_string[ofp.OFP_HEADER_BYTES:])
+        return error_to_class_map[sub_hdr.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 = ofp.ofp_header()
+    hdr.unpack(binary_string)
+
+    return hdr
+
+map_wc_field_to_match_member = {
+    'OFPFW_DL_VLAN'                 : 'dl_vlan',
+    'OFPFW_DL_SRC'                  : 'dl_src',
+    'OFPFW_DL_DST'                  : 'dl_dst',
+    'OFPFW_DL_TYPE'                 : 'dl_type',
+    'OFPFW_NW_PROTO'                : 'nw_proto',
+    'OFPFW_TP_SRC'                  : 'tp_src',
+    'OFPFW_TP_DST'                  : 'tp_dst',
+    'OFPFW_NW_SRC_SHIFT'            : 'nw_src_shift',
+    'OFPFW_NW_SRC_BITS'             : 'nw_src_bits',
+    'OFPFW_NW_SRC_MASK'             : 'nw_src_mask',
+    'OFPFW_NW_SRC_ALL'              : 'nw_src_all',
+    'OFPFW_NW_DST_SHIFT'            : 'nw_dst_shift',
+    'OFPFW_NW_DST_BITS'             : 'nw_dst_bits',
+    'OFPFW_NW_DST_MASK'             : 'nw_dst_mask',
+    'OFPFW_NW_DST_ALL'              : 'nw_dst_all',
+    'OFPFW_DL_VLAN_PCP'             : 'dl_vlan_pcp',
+    'OFPFW_NW_TOS'                  : 'nw_tos'
+}
+
+
+def parse_mac(mac_str):
+    """
+    Parse a MAC address
+
+    Parse a MAC address ':' separated string of hex digits to an
+    array of integer values.  '00:d0:05:5d:24:00' => [0, 208, 5, 93, 36, 0]
+    @param mac_str The string to convert
+    @return Array of 6 integer values
+    """
+    return map(lambda val:eval("0x" + val), mac_str.split(":"))
+
+def parse_ip(ip_str):
+    """
+    Parse an IP address
+
+    Parse an IP address '.' separated string of decimal digits to an
+    host ordered integer.  '172.24.74.77' => 
+    @param ip_str The string to convert
+    @return Integer value
+    """
+    array = map(lambda val:eval(val),ip_str.split("."))
+    val = 0
+    for a in array:
+        val <<= 8
+        val += a
+    return val
+
+def packet_to_flow_match(packet):
+    """
+    Create a flow match that matches packet with the given wildcards
+
+    @param packet The packet to use as a flow template
+    @param pkt_format Currently only L2 is supported.  Will indicate the 
+    overall packet type for parsing
+    @return An ofp_match object if successful.  None if format is not
+    recognized.  The wildcards of the match will be cleared for the
+    values extracted from the packet.
+
+    @todo check min length of packet
+    @todo Check if packet is other than L2 format
+    @todo Implement ICMP and ARP fields
+    """
+
+    return packet.parse()