blob: 67af1e7c3dc27e460a1b63d2a469f1364b3efff7 [file] [log] [blame]
Rich Lanea06d0c32013-03-25 08:52:03 -07001# Copyright 2013, Big Switch Networks, Inc.
2#
3# LoxiGen is licensed under the Eclipse Public License, version 1.0 (EPL), with
4# the following special exception:
5#
6# LOXI Exception
7#
8# As a special exception to the terms of the EPL, you may distribute libraries
9# generated by LoxiGen (LoxiGen Libraries) under the terms of your choice, provided
10# that copyright and licensing notices generated by LoxiGen are not altered or removed
11# from the LoxiGen Libraries and the notice provided below is (i) included in
12# the LoxiGen Libraries, if distributed in source code form and (ii) included in any
13# documentation for the LoxiGen Libraries, if distributed in binary form.
14#
15# Notice: "Copyright 2013, Big Switch Networks, Inc. This library was generated by the LoxiGen Compiler."
16#
17# You may not use this file except in compliance with the EPL or LOXI Exception. You may obtain
18# a copy of the EPL at:
19#
20# http://www.eclipse.org/legal/epl-v10.html
21#
22# Unless required by applicable law or agreed to in writing, software
23# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
24# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
25# EPL for the specific language governing permissions and limitations
26# under the EPL.
27
Rich Lane8a22cda2013-06-19 13:20:07 -070028from collections import namedtuple
29
30OFTypeData = namedtuple("OFTypeData", ["init", "pack", "unpack"])
31
Rich Lanec854bae2013-06-19 14:39:51 -070032# Map from LOXI type name to an object with templates for init, pack, and unpack
33# Most types are defined using the convenience code below. This dict should
34# only be used directly for special cases such as primitive types.
Rich Laneda11f8b2013-06-19 15:53:25 -070035type_data_map = {
Rich Lane8a22cda2013-06-19 13:20:07 -070036 'char': OFTypeData(
37 init='0',
38 pack='struct.pack("!B", %s)',
39 unpack='%s.read("!B")[0]'),
40
41 'uint8_t': OFTypeData(
42 init='0',
43 pack='struct.pack("!B", %s)',
44 unpack='%s.read("!B")[0]'),
45
46 'uint16_t': OFTypeData(
47 init='0',
48 pack='struct.pack("!H", %s)',
49 unpack='%s.read("!H")[0]'),
50
51 'uint32_t': OFTypeData(
52 init='0',
53 pack='struct.pack("!L", %s)',
54 unpack='%s.read("!L")[0]'),
55
56 'uint64_t': OFTypeData(
57 init='0',
58 pack='struct.pack("!Q", %s)',
59 unpack='%s.read("!Q")[0]'),
60
61 'of_port_no_t': OFTypeData(
62 init='0',
63 pack='util.pack_port_no(%s)',
64 unpack='util.unpack_port_no(%s)'),
65
66 'of_fm_cmd_t': OFTypeData(
67 init='0',
68 pack='util.pack_fm_cmd(%s)',
69 unpack='util.unpack_fm_cmd(%s)'),
70
71 'of_wc_bmap_t': OFTypeData(
72 init='util.init_wc_bmap()',
73 pack='util.pack_wc_bmap(%s)',
74 unpack='util.unpack_wc_bmap(%s)'),
75
76 'of_match_bmap_t': OFTypeData(
77 init='util.init_match_bmap()',
78 pack='util.pack_match_bmap(%s)',
79 unpack='util.unpack_match_bmap(%s)'),
80
81 'of_ipv6_t': OFTypeData(
82 init="'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'",
83 pack='struct.pack("!16s", %s)',
84 unpack="%s.read('!16s')[0]"),
85
86 'of_mac_addr_t': OFTypeData(
87 init='[0,0,0,0,0,0]',
88 pack='struct.pack("!6B", *%s)',
89 unpack="list(%s.read('!6B'))"),
90
91 'of_octets_t': OFTypeData(
92 init="''",
93 pack='%s',
94 unpack='str(%s.read_all())'),
95
Rich Lane8a22cda2013-06-19 13:20:07 -070096 # HACK need the match_v3 length field
97 'list(of_oxm_t)': OFTypeData(
98 init='[]',
99 pack='util.pack_list(%s)',
100 unpack='oxm.unpack_list(%s.slice(_length-4))'),
101
Rich Lanebe90eae2013-07-22 16:44:26 -0700102 'of_oxm_t': OFTypeData(
103 init='None',
104 pack='%s.pack()',
105 unpack='oxm.unpack(%s)'),
106
Rich Lanec854bae2013-06-19 14:39:51 -0700107 # TODO implement unpack
108 'list(of_table_features_t)': OFTypeData(
Rich Lane8a22cda2013-06-19 13:20:07 -0700109 init='[]',
110 pack='util.pack_list(%s)',
Rich Lanec854bae2013-06-19 14:39:51 -0700111 unpack=None),
Rich Lane8a22cda2013-06-19 13:20:07 -0700112
Rich Lanec854bae2013-06-19 14:39:51 -0700113 # TODO implement unpack
Rich Lane8a22cda2013-06-19 13:20:07 -0700114 'list(of_action_id_t)': OFTypeData(
115 init='[]',
116 pack='util.pack_list(%s)',
117 unpack=None),
118
Rich Lanec854bae2013-06-19 14:39:51 -0700119 # TODO implement unpack
Rich Lane8a22cda2013-06-19 13:20:07 -0700120 'list(of_table_feature_prop_t)': OFTypeData(
121 init='[]',
122 pack='util.pack_list(%s)',
123 unpack=None),
Rich Lane8a22cda2013-06-19 13:20:07 -0700124}
Rich Lanea06d0c32013-03-25 08:52:03 -0700125
Rich Lanec854bae2013-06-19 14:39:51 -0700126## Fixed length strings
127
128# Map from class name to length
129fixed_length_strings = {
130 'of_port_name_t': 16,
131 'of_table_name_t': 32,
132 'of_serial_num_t': 32,
133 'of_desc_str_t': 256,
134}
135
136for (cls, length) in fixed_length_strings.items():
Rich Laneda11f8b2013-06-19 15:53:25 -0700137 type_data_map[cls] = OFTypeData(
Rich Lanec854bae2013-06-19 14:39:51 -0700138 init='""',
139 pack='struct.pack("!%ds", %%s)' % length,
140 unpack='%%s.read("!%ds")[0].rstrip("\\x00")' % length)
141
142## Embedded structs
143
144# Map from class name to Python class name
145embedded_structs = {
146 'of_match_t': 'common.match',
147 'of_port_desc_t': 'common.port_desc',
148 'of_meter_features_t': 'common.meter_features',
149 'of_bsn_vport_q_in_q_t': 'common.bsn_vport_q_in_q',
150}
151
152for (cls, pyclass) in embedded_structs.items():
Rich Laneda11f8b2013-06-19 15:53:25 -0700153 type_data_map[cls] = OFTypeData(
Rich Lanec854bae2013-06-19 14:39:51 -0700154 init='%s()' % pyclass,
155 pack='%s.pack()',
156 unpack='%s.unpack(%%s)' % pyclass)
157
158## Variable element length lists
159
160# Map from list class name to list deserializer
161variable_elem_len_lists = {
162 'list(of_action_t)': 'action.unpack_list',
163 'list(of_bucket_t)': 'common.unpack_list_bucket',
164 'list(of_flow_stats_entry_t)': 'common.unpack_list_flow_stats_entry',
165 'list(of_group_desc_stats_entry_t)': 'common.unpack_list_group_desc_stats_entry',
166 'list(of_group_stats_entry_t)': 'common.unpack_list_group_stats_entry',
167 'list(of_hello_elem_t)': 'common.unpack_list_hello_elem',
168 'list(of_instruction_t)': 'instruction.unpack_list',
169 'list(of_meter_band_t)': 'meter_band.unpack_list',
170 'list(of_meter_stats_t)': 'common.unpack_list_meter_stats',
171 'list(of_packet_queue_t)': 'common.unpack_list_packet_queue',
172 'list(of_queue_prop_t)': 'common.unpack_list_queue_prop',
173}
174
175for (cls, deserializer) in variable_elem_len_lists.items():
Rich Laneda11f8b2013-06-19 15:53:25 -0700176 type_data_map[cls] = OFTypeData(
Rich Lanec854bae2013-06-19 14:39:51 -0700177 init='[]',
178 pack='util.pack_list(%s)',
179 unpack='%s(%%s)' % deserializer)
180
181## Fixed element length lists
182
183# Map from list class name to list element deserializer
184fixed_elem_len_lists = {
185 'list(of_bsn_interface_t)': 'common.bsn_interface.unpack',
186 'list(of_bucket_counter_t)': 'common.bucket_counter.unpack',
187 'list(of_meter_band_stats_t)': 'common.meter_band_stats.unpack',
188 'list(of_port_desc_t)': 'common.port_desc.unpack',
189 'list(of_port_stats_entry_t)': 'common.port_stats_entry.unpack',
190 'list(of_queue_stats_entry_t)': 'common.queue_stats_entry.unpack',
191 'list(of_table_stats_entry_t)': 'common.table_stats_entry.unpack',
192 'list(of_uint32_t)': 'common.uint32.unpack',
193 'list(of_uint8_t)': 'common.uint8.unpack',
194}
195
196for (cls, element_deserializer) in fixed_elem_len_lists.items():
Rich Laneda11f8b2013-06-19 15:53:25 -0700197 type_data_map[cls] = OFTypeData(
Rich Lanec854bae2013-06-19 14:39:51 -0700198 init='[]',
199 pack='util.pack_list(%s)',
200 unpack='loxi.generic_util.unpack_list(%%s, %s)' % element_deserializer)
201
Rich Laneda11f8b2013-06-19 15:53:25 -0700202## Public interface
Rich Lanec854bae2013-06-19 14:39:51 -0700203
Rich Laneda11f8b2013-06-19 15:53:25 -0700204# Return an initializer expression for the given oftype
205def gen_init_expr(oftype):
206 type_data = type_data_map.get(oftype)
207 if type_data and type_data.init:
208 return type_data.init
209 else:
210 return "loxi.unimplemented('init %s')" % oftype
Rich Lanea06d0c32013-03-25 08:52:03 -0700211
Rich Laneda11f8b2013-06-19 15:53:25 -0700212# Return a pack expression for the given oftype
213#
214# 'value_expr' is a string of Python code which will evaluate to
215# the value to be packed.
216def gen_pack_expr(oftype, value_expr):
217 type_data = type_data_map.get(oftype)
218 if type_data and type_data.pack:
219 return type_data.pack % value_expr
220 else:
221 return "loxi.unimplemented('pack %s')" % oftype
Rich Lanea06d0c32013-03-25 08:52:03 -0700222
Rich Laneda11f8b2013-06-19 15:53:25 -0700223# Return an unpack expression for the given oftype
224#
225# 'reader_expr' is a string of Python code which will evaluate to
226# the OFReader instance used for deserialization.
227def gen_unpack_expr(oftype, reader_expr):
228 type_data = type_data_map.get(oftype)
229 if type_data and type_data.unpack:
230 return type_data.unpack % reader_expr
231 else:
232 return "loxi.unimplemented('unpack %s')" % oftype