blob: c378cea4f52df79ecbc078c73aa60e907239c1de [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
Andreas Wundsam69ecfdc2013-09-17 13:50:12 -070030import loxi_utils.loxi_utils as loxi_utils
31import of_g
32
Rich Lane8a22cda2013-06-19 13:20:07 -070033OFTypeData = namedtuple("OFTypeData", ["init", "pack", "unpack"])
34
Rich Lanec854bae2013-06-19 14:39:51 -070035# Map from LOXI type name to an object with templates for init, pack, and unpack
36# Most types are defined using the convenience code below. This dict should
37# only be used directly for special cases such as primitive types.
Rich Laneda11f8b2013-06-19 15:53:25 -070038type_data_map = {
Rich Lane8a22cda2013-06-19 13:20:07 -070039 'char': OFTypeData(
40 init='0',
41 pack='struct.pack("!B", %s)',
42 unpack='%s.read("!B")[0]'),
43
44 'uint8_t': OFTypeData(
45 init='0',
46 pack='struct.pack("!B", %s)',
47 unpack='%s.read("!B")[0]'),
48
49 'uint16_t': OFTypeData(
50 init='0',
51 pack='struct.pack("!H", %s)',
52 unpack='%s.read("!H")[0]'),
53
54 'uint32_t': OFTypeData(
55 init='0',
56 pack='struct.pack("!L", %s)',
57 unpack='%s.read("!L")[0]'),
58
59 'uint64_t': OFTypeData(
60 init='0',
61 pack='struct.pack("!Q", %s)',
62 unpack='%s.read("!Q")[0]'),
63
64 'of_port_no_t': OFTypeData(
65 init='0',
66 pack='util.pack_port_no(%s)',
67 unpack='util.unpack_port_no(%s)'),
68
69 'of_fm_cmd_t': OFTypeData(
70 init='0',
71 pack='util.pack_fm_cmd(%s)',
72 unpack='util.unpack_fm_cmd(%s)'),
73
74 'of_wc_bmap_t': OFTypeData(
75 init='util.init_wc_bmap()',
76 pack='util.pack_wc_bmap(%s)',
77 unpack='util.unpack_wc_bmap(%s)'),
78
79 'of_match_bmap_t': OFTypeData(
80 init='util.init_match_bmap()',
81 pack='util.pack_match_bmap(%s)',
82 unpack='util.unpack_match_bmap(%s)'),
83
Andreas Wundsamb566a162013-07-18 19:30:23 -070084 'of_ipv4_t': OFTypeData(
85 init='0',
86 pack='struct.pack("!L", %s)',
87 unpack='%s.read("!L")[0]'),
88
Rich Lane8a22cda2013-06-19 13:20:07 -070089 'of_ipv6_t': OFTypeData(
90 init="'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'",
91 pack='struct.pack("!16s", %s)',
92 unpack="%s.read('!16s')[0]"),
93
94 'of_mac_addr_t': OFTypeData(
95 init='[0,0,0,0,0,0]',
96 pack='struct.pack("!6B", *%s)',
97 unpack="list(%s.read('!6B'))"),
98
99 'of_octets_t': OFTypeData(
100 init="''",
101 pack='%s',
102 unpack='str(%s.read_all())'),
103
Rich Lane3b2fd832013-09-24 13:44:08 -0700104 'of_bitmap_128_t': OFTypeData(
105 init='set()',
106 pack='util.pack_bitmap_128(%s)',
107 unpack="util.unpack_bitmap_128(%s)"),
108
Rich Lane8a22cda2013-06-19 13:20:07 -0700109 # HACK need the match_v3 length field
110 'list(of_oxm_t)': OFTypeData(
111 init='[]',
112 pack='util.pack_list(%s)',
113 unpack='oxm.unpack_list(%s.slice(_length-4))'),
114
Rich Lanebe90eae2013-07-22 16:44:26 -0700115 'of_oxm_t': OFTypeData(
116 init='None',
117 pack='%s.pack()',
118 unpack='oxm.unpack(%s)'),
119
Rich Lanec854bae2013-06-19 14:39:51 -0700120 # TODO implement unpack
121 'list(of_table_features_t)': OFTypeData(
Rich Lane8a22cda2013-06-19 13:20:07 -0700122 init='[]',
123 pack='util.pack_list(%s)',
Rich Lanec854bae2013-06-19 14:39:51 -0700124 unpack=None),
Rich Lane8a22cda2013-06-19 13:20:07 -0700125
Rich Lanec854bae2013-06-19 14:39:51 -0700126 # TODO implement unpack
Rich Lane8a22cda2013-06-19 13:20:07 -0700127 'list(of_action_id_t)': OFTypeData(
128 init='[]',
129 pack='util.pack_list(%s)',
130 unpack=None),
131
Rich Lanec854bae2013-06-19 14:39:51 -0700132 # TODO implement unpack
Rich Lane8a22cda2013-06-19 13:20:07 -0700133 'list(of_table_feature_prop_t)': OFTypeData(
134 init='[]',
135 pack='util.pack_list(%s)',
136 unpack=None),
Rich Lane8a22cda2013-06-19 13:20:07 -0700137}
Rich Lanea06d0c32013-03-25 08:52:03 -0700138
Rich Lanec854bae2013-06-19 14:39:51 -0700139## Fixed length strings
140
141# Map from class name to length
142fixed_length_strings = {
143 'of_port_name_t': 16,
144 'of_table_name_t': 32,
145 'of_serial_num_t': 32,
146 'of_desc_str_t': 256,
147}
148
149for (cls, length) in fixed_length_strings.items():
Rich Laneda11f8b2013-06-19 15:53:25 -0700150 type_data_map[cls] = OFTypeData(
Rich Lanec854bae2013-06-19 14:39:51 -0700151 init='""',
152 pack='struct.pack("!%ds", %%s)' % length,
153 unpack='%%s.read("!%ds")[0].rstrip("\\x00")' % length)
154
155## Embedded structs
156
157# Map from class name to Python class name
158embedded_structs = {
159 'of_match_t': 'common.match',
160 'of_port_desc_t': 'common.port_desc',
161 'of_meter_features_t': 'common.meter_features',
162 'of_bsn_vport_q_in_q_t': 'common.bsn_vport_q_in_q',
163}
164
165for (cls, pyclass) in embedded_structs.items():
Rich Laneda11f8b2013-06-19 15:53:25 -0700166 type_data_map[cls] = OFTypeData(
Rich Lanec854bae2013-06-19 14:39:51 -0700167 init='%s()' % pyclass,
168 pack='%s.pack()',
169 unpack='%s.unpack(%%s)' % pyclass)
170
171## Variable element length lists
172
173# Map from list class name to list deserializer
174variable_elem_len_lists = {
175 'list(of_action_t)': 'action.unpack_list',
176 'list(of_bucket_t)': 'common.unpack_list_bucket',
177 'list(of_flow_stats_entry_t)': 'common.unpack_list_flow_stats_entry',
178 'list(of_group_desc_stats_entry_t)': 'common.unpack_list_group_desc_stats_entry',
179 'list(of_group_stats_entry_t)': 'common.unpack_list_group_stats_entry',
180 'list(of_hello_elem_t)': 'common.unpack_list_hello_elem',
181 'list(of_instruction_t)': 'instruction.unpack_list',
182 'list(of_meter_band_t)': 'meter_band.unpack_list',
183 'list(of_meter_stats_t)': 'common.unpack_list_meter_stats',
184 'list(of_packet_queue_t)': 'common.unpack_list_packet_queue',
185 'list(of_queue_prop_t)': 'common.unpack_list_queue_prop',
186}
187
188for (cls, deserializer) in variable_elem_len_lists.items():
Rich Laneda11f8b2013-06-19 15:53:25 -0700189 type_data_map[cls] = OFTypeData(
Rich Lanec854bae2013-06-19 14:39:51 -0700190 init='[]',
191 pack='util.pack_list(%s)',
192 unpack='%s(%%s)' % deserializer)
193
194## Fixed element length lists
195
196# Map from list class name to list element deserializer
197fixed_elem_len_lists = {
198 'list(of_bsn_interface_t)': 'common.bsn_interface.unpack',
199 'list(of_bucket_counter_t)': 'common.bucket_counter.unpack',
200 'list(of_meter_band_stats_t)': 'common.meter_band_stats.unpack',
201 'list(of_port_desc_t)': 'common.port_desc.unpack',
202 'list(of_port_stats_entry_t)': 'common.port_stats_entry.unpack',
203 'list(of_queue_stats_entry_t)': 'common.queue_stats_entry.unpack',
204 'list(of_table_stats_entry_t)': 'common.table_stats_entry.unpack',
205 'list(of_uint32_t)': 'common.uint32.unpack',
206 'list(of_uint8_t)': 'common.uint8.unpack',
207}
208
209for (cls, element_deserializer) in fixed_elem_len_lists.items():
Rich Laneda11f8b2013-06-19 15:53:25 -0700210 type_data_map[cls] = OFTypeData(
Rich Lanec854bae2013-06-19 14:39:51 -0700211 init='[]',
212 pack='util.pack_list(%s)',
213 unpack='loxi.generic_util.unpack_list(%%s, %s)' % element_deserializer)
214
Rich Laneda11f8b2013-06-19 15:53:25 -0700215## Public interface
Rich Lanec854bae2013-06-19 14:39:51 -0700216
Andreas Wundsam69ecfdc2013-09-17 13:50:12 -0700217def lookup_type_data(oftype, version):
218 return type_data_map.get(loxi_utils.lookup_ir_wiretype(oftype, version))
219
Rich Laneda11f8b2013-06-19 15:53:25 -0700220# Return an initializer expression for the given oftype
Andreas Wundsam69ecfdc2013-09-17 13:50:12 -0700221def gen_init_expr(oftype, version):
222 type_data = lookup_type_data(oftype, version)
Rich Laneda11f8b2013-06-19 15:53:25 -0700223 if type_data and type_data.init:
224 return type_data.init
225 else:
226 return "loxi.unimplemented('init %s')" % oftype
Rich Lanea06d0c32013-03-25 08:52:03 -0700227
Rich Laneda11f8b2013-06-19 15:53:25 -0700228# Return a pack expression for the given oftype
229#
230# 'value_expr' is a string of Python code which will evaluate to
231# the value to be packed.
Andreas Wundsam69ecfdc2013-09-17 13:50:12 -0700232def gen_pack_expr(oftype, value_expr, version):
233 type_data = lookup_type_data(oftype, version)
Rich Laneda11f8b2013-06-19 15:53:25 -0700234 if type_data and type_data.pack:
235 return type_data.pack % value_expr
236 else:
237 return "loxi.unimplemented('pack %s')" % oftype
Rich Lanea06d0c32013-03-25 08:52:03 -0700238
Rich Laneda11f8b2013-06-19 15:53:25 -0700239# Return an unpack expression for the given oftype
240#
241# 'reader_expr' is a string of Python code which will evaluate to
242# the OFReader instance used for deserialization.
Andreas Wundsam69ecfdc2013-09-17 13:50:12 -0700243def gen_unpack_expr(oftype, reader_expr, version):
244 type_data = lookup_type_data(oftype, version)
Rich Laneda11f8b2013-06-19 15:53:25 -0700245 if type_data and type_data.unpack:
246 return type_data.unpack % reader_expr
247 else:
248 return "loxi.unimplemented('unpack %s')" % oftype