| # Copyright 2013, Big Switch Networks, Inc. |
| # |
| # LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with |
| # the following special exception: |
| # |
| # LOXI Exception |
| # |
| # As a special exception to the terms of the EPL, you may distribute libraries |
| # generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided |
| # that copyright and licensing notices generated by LoxiGen are not altered or removed |
| # from the LoxiGen Libraries and the notice provided below is (i) included in |
| # the LoxiGen Libraries, if distributed in source code form and (ii) included in any |
| # documentation for the LoxiGen Libraries, if distributed in binary form. |
| # |
| # Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler." |
| # |
| # You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain |
| # a copy of the EPL at: |
| # |
| # http://www.eclipse.org/legal/epl-v10.html |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| # EPL for the specific language governing permissions and limitations |
| # under the EPL. |
| |
| from collections import namedtuple |
| |
| OFTypeData = namedtuple("OFTypeData", ["init", "pack", "unpack"]) |
| |
| type_data = { |
| |
| ## Primitives |
| |
| 'char': OFTypeData( |
| init='0', |
| pack='struct.pack("!B", %s)', |
| unpack='%s.read("!B")[0]'), |
| |
| 'uint8_t': OFTypeData( |
| init='0', |
| pack='struct.pack("!B", %s)', |
| unpack='%s.read("!B")[0]'), |
| |
| 'uint16_t': OFTypeData( |
| init='0', |
| pack='struct.pack("!H", %s)', |
| unpack='%s.read("!H")[0]'), |
| |
| 'uint32_t': OFTypeData( |
| init='0', |
| pack='struct.pack("!L", %s)', |
| unpack='%s.read("!L")[0]'), |
| |
| 'uint64_t': OFTypeData( |
| init='0', |
| pack='struct.pack("!Q", %s)', |
| unpack='%s.read("!Q")[0]'), |
| |
| 'of_port_no_t': OFTypeData( |
| init='0', |
| pack='util.pack_port_no(%s)', |
| unpack='util.unpack_port_no(%s)'), |
| |
| 'of_fm_cmd_t': OFTypeData( |
| init='0', |
| pack='util.pack_fm_cmd(%s)', |
| unpack='util.unpack_fm_cmd(%s)'), |
| |
| 'of_wc_bmap_t': OFTypeData( |
| init='util.init_wc_bmap()', |
| pack='util.pack_wc_bmap(%s)', |
| unpack='util.unpack_wc_bmap(%s)'), |
| |
| 'of_match_bmap_t': OFTypeData( |
| init='util.init_match_bmap()', |
| pack='util.pack_match_bmap(%s)', |
| unpack='util.unpack_match_bmap(%s)'), |
| |
| 'of_ipv6_t': OFTypeData( |
| init="'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'", |
| pack='struct.pack("!16s", %s)', |
| unpack="%s.read('!16s')[0]"), |
| |
| 'of_mac_addr_t': OFTypeData( |
| init='[0,0,0,0,0,0]', |
| pack='struct.pack("!6B", *%s)', |
| unpack="list(%s.read('!6B'))"), |
| |
| 'of_octets_t': OFTypeData( |
| init="''", |
| pack='%s', |
| unpack='str(%s.read_all())'), |
| |
| ## Strings |
| |
| 'of_port_name_t': OFTypeData( |
| init="''", |
| pack='struct.pack("!16s", %s)', |
| unpack='%s.read("!16s")[0].rstrip("\\x00")'), |
| |
| 'of_table_name_t': OFTypeData( |
| init="''", |
| pack='struct.pack("!32s", %s)', |
| unpack='%s.read("!32s")[0].rstrip("\\x00")'), |
| |
| 'of_serial_num_t': OFTypeData( |
| init="''", |
| pack='struct.pack("!32s", %s)', |
| unpack='%s.read("!32s")[0].rstrip("\\x00")'), |
| |
| 'of_desc_str_t': OFTypeData( |
| init="''", |
| pack='struct.pack("!256s", %s)', |
| unpack='%s.read("!256s")[0].rstrip("\\x00")'), |
| |
| ## Embedded structs |
| # TODO add helper to generate these |
| |
| 'of_match_t': OFTypeData( |
| init='common.match()', |
| pack='%s.pack()', |
| unpack='common.match.unpack(%s)'), |
| |
| 'of_port_desc_t': OFTypeData( |
| init='common.port_desc()', |
| pack='%s.pack()', |
| unpack='common.port_desc.unpack(%s)'), |
| |
| 'of_meter_features_t': OFTypeData( |
| init='common.meter_features()', |
| pack='%s.pack()', |
| unpack='common.meter_features.unpack(%s)'), |
| |
| 'of_bsn_vport_q_in_q_t': OFTypeData( |
| init='common.bsn_vport_q_in_q()', |
| pack='%s.pack()', |
| unpack='common.bsn_vport_q_in_q.unpack(%s)'), |
| |
| ## TLV Lists |
| |
| 'list(of_action_t)': OFTypeData( |
| init='[]', |
| pack='util.pack_list(%s)', |
| unpack='action.unpack_list(%s)'), |
| |
| 'list(of_table_features_t)': OFTypeData( |
| init='[]', |
| pack='util.pack_list(%s)', |
| unpack=None), |
| |
| 'list(of_flow_stats_entry_t)': OFTypeData( |
| init='[]', |
| pack='util.pack_list(%s)', |
| unpack='common.unpack_list_flow_stats_entry(%s)'), |
| |
| 'list(of_bucket_t)': OFTypeData( |
| init='[]', |
| pack='util.pack_list(%s)', |
| unpack='common.unpack_list_bucket(%s)'), |
| |
| 'list(of_packet_queue_t)': OFTypeData( |
| init='[]', |
| pack='util.pack_list(%s)', |
| unpack='common.unpack_list_packet_queue(%s)'), |
| |
| 'list(of_meter_stats_t)': OFTypeData( |
| init='[]', |
| pack='util.pack_list(%s)', |
| unpack='common.unpack_list_meter_stats(%s)'), |
| |
| # HACK need the match_v3 length field |
| 'list(of_oxm_t)': OFTypeData( |
| init='[]', |
| pack='util.pack_list(%s)', |
| unpack='oxm.unpack_list(%s.slice(_length-4))'), |
| |
| 'list(of_group_stats_entry_t)': OFTypeData( |
| init='[]', |
| pack='util.pack_list(%s)', |
| unpack='common.unpack_list_group_stats_entry(%s)'), |
| |
| 'list(of_hello_elem_t)': OFTypeData( |
| init='[]', |
| pack='util.pack_list(%s)', |
| unpack='common.unpack_list_hello_elem(%s)'), |
| |
| 'list(of_action_id_t)': OFTypeData( |
| init='[]', |
| pack='util.pack_list(%s)', |
| unpack=None), |
| |
| 'list(of_group_desc_stats_entry_t)': OFTypeData( |
| init='[]', |
| pack='util.pack_list(%s)', |
| unpack='common.unpack_list_group_desc_stats_entry(%s)'), |
| |
| 'list(of_queue_prop_t)': OFTypeData( |
| init='[]', |
| pack='util.pack_list(%s)', |
| unpack='common.unpack_list_queue_prop(%s)'), |
| |
| 'list(of_instruction_t)': OFTypeData( |
| init='[]', |
| pack='util.pack_list(%s)', |
| unpack='instruction.unpack_list(%s)'), |
| |
| 'list(of_table_feature_prop_t)': OFTypeData( |
| init='[]', |
| pack='util.pack_list(%s)', |
| unpack=None), |
| |
| 'list(of_meter_band_t)': OFTypeData( |
| init='[]', |
| pack='util.pack_list(%s)', |
| unpack='meter_band.unpack_list(%s)'), |
| |
| ## Lists with fixed-length elements |
| |
| 'list(of_bucket_counter_t)': OFTypeData( |
| init='[]', |
| pack='util.pack_list(%s)', |
| unpack='loxi.generic_util.unpack_list(%s, common.bucket_counter.unpack)'), |
| |
| 'list(of_uint32_t)': OFTypeData( |
| init='[]', |
| pack='util.pack_list(%s)', |
| unpack='loxi.generic_util.unpack_list(%s, common.uint32.unpack)'), |
| |
| 'list(of_queue_stats_entry_t)': OFTypeData( |
| init='[]', |
| pack='util.pack_list(%s)', |
| unpack='loxi.generic_util.unpack_list(%s, common.queue_stats_entry.unpack)'), |
| |
| 'list(of_table_stats_entry_t)': OFTypeData( |
| init='[]', |
| pack='util.pack_list(%s)', |
| unpack='loxi.generic_util.unpack_list(%s, common.table_stats_entry.unpack)'), |
| |
| 'list(of_uint8_t)': OFTypeData( |
| init='[]', |
| pack='util.pack_list(%s)', |
| unpack='loxi.generic_util.unpack_list(%s, common.uint8.unpack)'), |
| |
| 'list(of_port_stats_entry_t)': OFTypeData( |
| init='[]', |
| pack='util.pack_list(%s)', |
| unpack='loxi.generic_util.unpack_list(%s, common.port_stats_entry.unpack)'), |
| |
| 'list(of_bsn_interface_t)': OFTypeData( |
| init='[]', |
| pack='util.pack_list(%s)', |
| unpack='loxi.generic_util.unpack_list(%s, common.bsn_interface.unpack)'), |
| |
| 'list(of_meter_band_stats_t)': OFTypeData( |
| init='[]', |
| pack='util.pack_list(%s)', |
| unpack='loxi.generic_util.unpack_list(%s, common.meter_band_stats.unpack)'), |
| |
| 'list(of_port_desc_t)': OFTypeData( |
| init='[]', |
| pack='util.pack_list(%s)', |
| unpack='loxi.generic_util.unpack_list(%s, common.port_desc.unpack)'), |
| } |
| |
| class OFType(object): |
| """ |
| Encapsulates knowledge about the OpenFlow type system. |
| """ |
| |
| version = None |
| base = None |
| |
| def __init__(self, string, version): |
| self.version = version |
| self.base = string |
| self.type_data = type_data.get(self.base) |
| |
| def gen_init_expr(self): |
| if self.type_data and self.type_data.init: |
| return self.type_data.init |
| else: |
| return "loxi.unimplemented('init %s')" % self.base |
| |
| def gen_pack_expr(self, value_expr): |
| if self.type_data and self.type_data.pack: |
| return self.type_data.pack % value_expr |
| else: |
| "loxi.unimplemented('pack %s')" % self.base |
| |
| def gen_unpack_expr(self, reader_expr): |
| if self.type_data and self.type_data.unpack: |
| return self.type_data.unpack % reader_expr |
| else: |
| "loxi.unimplemented('unpack %s')" % self.base |