Dan Talayco | b9cb548 | 2010-02-09 15:23:12 -0800 | [diff] [blame^] | 1 | o |
Dan Talayco | f75360a | 2010-02-05 22:22:54 -0800 | [diff] [blame] | 2 | from message import * |
| 3 | from error import * |
| 4 | from action import * |
| 5 | from action_list import action_list |
| 6 | from ofp import * |
| 7 | |
| 8 | """ |
| 9 | of_message.py |
| 10 | Contains wrapper functions and classes for the of_message namespace |
| 11 | that are generated by hand. It includes the rest of the wrapper |
| 12 | function information into the of_message namespace |
| 13 | """ |
| 14 | |
| 15 | # These message types are subclassed |
| 16 | msg_type_subclassed = [ |
| 17 | OFPT_STATS_REQUEST, |
| 18 | OFPT_STATS_REPLY, |
| 19 | OFPT_ERROR |
| 20 | ] |
| 21 | |
| 22 | # Maps from sub-types to classes |
| 23 | stats_reply_to_class_map = { |
| 24 | OFPST_DESC : desc_stats_reply, |
| 25 | OFPST_AGGREGATE : aggregate_stats_reply, |
| 26 | OFPST_FLOW : flow_stats_reply, |
| 27 | OFPST_TABLE : table_stats_reply, |
| 28 | OFPST_PORT : port_stats_reply, |
| 29 | OFPST_QUEUE : queue_stats_reply |
| 30 | } |
| 31 | |
| 32 | stats_request_to_class_map = { |
| 33 | OFPST_DESC : desc_stats_request, |
| 34 | OFPST_AGGREGATE : aggregate_stats_request, |
| 35 | OFPST_FLOW : flow_stats_request, |
| 36 | OFPST_TABLE : table_stats_request, |
| 37 | OFPST_PORT : port_stats_request, |
| 38 | OFPST_QUEUE : queue_stats_request |
| 39 | } |
| 40 | |
| 41 | error_to_class_map = { |
| 42 | OFPET_HELLO_FAILED : hello_failed_error_msg, |
| 43 | OFPET_BAD_REQUEST : bad_request_error_msg, |
| 44 | OFPET_BAD_ACTION : bad_action_error_msg, |
| 45 | OFPET_FLOW_MOD_FAILED : flow_mod_failed_error_msg, |
| 46 | OFPET_PORT_MOD_FAILED : port_mod_failed_error_msg, |
| 47 | OFPET_QUEUE_OP_FAILED : queue_op_failed_error_msg |
| 48 | } |
| 49 | |
| 50 | # Map from header type value to the underlieing message class |
| 51 | msg_type_to_class_map = { |
| 52 | OFPT_HELLO : hello, |
| 53 | OFPT_ERROR : error, |
| 54 | OFPT_ECHO_REQUEST : echo_request, |
| 55 | OFPT_ECHO_REPLY : echo_reply, |
| 56 | OFPT_VENDOR : vendor, |
| 57 | OFPT_FEATURES_REQUEST : features_request, |
| 58 | OFPT_FEATURES_REPLY : features_reply, |
| 59 | OFPT_GET_CONFIG_REQUEST : get_config_request, |
| 60 | OFPT_GET_CONFIG_REPLY : get_config_reply, |
| 61 | OFPT_SET_CONFIG : set_config, |
| 62 | OFPT_PACKET_IN : packet_in, |
| 63 | OFPT_FLOW_REMOVED : flow_removed, |
| 64 | OFPT_PORT_STATUS : port_status, |
| 65 | OFPT_PACKET_OUT : packet_out, |
| 66 | OFPT_FLOW_MOD : flow_mod, |
| 67 | OFPT_PORT_MOD : port_mod, |
| 68 | OFPT_STATS_REQUEST : stats_request, |
| 69 | OFPT_STATS_REPLY : stats_reply, |
| 70 | OFPT_BARRIER_REQUEST : barrier_request, |
| 71 | OFPT_BARRIER_REPLY : barrier_reply, |
| 72 | OFPT_QUEUE_GET_CONFIG_REQUEST : queue_get_config_request, |
| 73 | OFPT_QUEUE_GET_CONFIG_REPLY : queue_get_config_reply |
| 74 | } |
| 75 | |
| 76 | def _of_message_to_object(binary_string): |
| 77 | """ |
| 78 | Map a binary string to the corresponding class. |
| 79 | |
| 80 | Appropriately resolves subclasses |
| 81 | """ |
| 82 | hdr = ofp_header() |
| 83 | hdr.unpack(binary_string) |
| 84 | # FIXME: Add error detection |
| 85 | if not hdr.type in msg_type_subclassed: |
| 86 | return msg_type_to_class_map[hdr.type]() |
| 87 | if hdr.type == OFPT_STATS_REQUEST: |
Dan Talayco | b9cb548 | 2010-02-09 15:23:12 -0800 | [diff] [blame^] | 88 | sub_hdr = ofp_stats_request() |
| 89 | sub_hdr.unpack(binary_string) |
| 90 | return stats_request_to_class_map[sub_hdr.type]() |
Dan Talayco | f75360a | 2010-02-05 22:22:54 -0800 | [diff] [blame] | 91 | elif hdr.type == OFPT_STATS_REPLY: |
Dan Talayco | b9cb548 | 2010-02-09 15:23:12 -0800 | [diff] [blame^] | 92 | sub_hdr = ofp_stats_reply() |
| 93 | sub_hdr.unpack(binary_string) |
| 94 | return stats_reply_to_class_map[sub_hdr.type]() |
| 95 | elif hdr.type == OFPT_ERROR: |
| 96 | sub_hdr = ofp_error_msg() |
| 97 | sub_hdr.unpack(binary_string) |
| 98 | return error_to_class_map[sub_hdr.type]() |
Dan Talayco | f75360a | 2010-02-05 22:22:54 -0800 | [diff] [blame] | 99 | else: |
| 100 | print "ERROR parsing packet to object" |
| 101 | return None |
| 102 | |
| 103 | def of_message_parse(binary_string, raw=False): |
| 104 | """ |
| 105 | Parse an OpenFlow packet |
| 106 | |
| 107 | Parses a raw OpenFlow packet into a Python class, with class |
| 108 | members fully populated. |
| 109 | |
| 110 | @param binary_string The packet (string) to be parsed |
Dan Talayco | f75360a | 2010-02-05 22:22:54 -0800 | [diff] [blame] | 111 | @param raw If true, interpret the packet as an L2 packet. Not |
| 112 | yet supported. |
Dan Talayco | f75360a | 2010-02-05 22:22:54 -0800 | [diff] [blame] | 113 | @return An object of some message class or None if fails |
| 114 | |
| 115 | """ |
| 116 | |
| 117 | if raw: |
| 118 | print "raw packet message parsing not supported" |
| 119 | return None |
| 120 | |
| 121 | obj = _of_message_to_object(binary_string) |
| 122 | if obj != None: |
| 123 | obj.unpack(binary_string) |
| 124 | return obj |
| 125 | |
Dan Talayco | b9cb548 | 2010-02-09 15:23:12 -0800 | [diff] [blame^] | 126 | |
| 127 | def of_header_parse(binary_string, raw=False): |
| 128 | """ |
| 129 | Parse only the header from an OpenFlow packet |
| 130 | |
| 131 | Parses the header from a raw OpenFlow packet into a |
| 132 | an ofp_header Python class. |
| 133 | |
| 134 | @param binary_string The packet (string) to be parsed |
| 135 | @param raw If true, interpret the packet as an L2 packet. Not |
| 136 | yet supported. |
| 137 | @return An ofp_header object |
| 138 | |
| 139 | """ |
| 140 | |
| 141 | if raw: |
| 142 | print "raw packet message parsing not supported" |
| 143 | return None |
| 144 | |
| 145 | hdr = ofp_header() |
| 146 | hdr.unpack(binary_string) |
| 147 | |
| 148 | return hdr |
| 149 | |
| 150 | def packet_to_flow(packet, wildcards=None, pkt_format="L2"): |
| 151 | """ |
| 152 | Create a flow that matches packet with the given wildcards |
| 153 | |
| 154 | @param packet The packet to use as a flow template |
| 155 | @param wildcards Wildcards to place in the flow (ignore those |
| 156 | fields from the packet) |
| 157 | @param pkt_format May be one string from: L2, L3, ? |
| 158 | Fields from unspecified layers are forced to be wildcards |
| 159 | |
| 160 | """ |
| 161 | |