blob: 9d249d401032f5f05ae0b52612a69ff20e5de440 [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
32type_data = {
33
34 ## Primitives
35
36 '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
96 ## Strings
97
98 'of_port_name_t': OFTypeData(
99 init="''",
100 pack='struct.pack("!16s", %s)',
101 unpack='%s.read("!16s")[0].rstrip("\\x00")'),
102
103 'of_table_name_t': OFTypeData(
104 init="''",
105 pack='struct.pack("!32s", %s)',
106 unpack='%s.read("!32s")[0].rstrip("\\x00")'),
107
108 'of_serial_num_t': OFTypeData(
109 init="''",
110 pack='struct.pack("!32s", %s)',
111 unpack='%s.read("!32s")[0].rstrip("\\x00")'),
112
113 'of_desc_str_t': OFTypeData(
114 init="''",
115 pack='struct.pack("!256s", %s)',
116 unpack='%s.read("!256s")[0].rstrip("\\x00")'),
117
118 ## Embedded structs
119 # TODO add helper to generate these
120
121 'of_match_t': OFTypeData(
122 init='common.match()',
123 pack='%s.pack()',
124 unpack='common.match.unpack(%s)'),
125
126 'of_port_desc_t': OFTypeData(
127 init='common.port_desc()',
128 pack='%s.pack()',
129 unpack='common.port_desc.unpack(%s)'),
130
131 'of_meter_features_t': OFTypeData(
132 init='common.meter_features()',
133 pack='%s.pack()',
134 unpack='common.meter_features.unpack(%s)'),
135
136 'of_bsn_vport_q_in_q_t': OFTypeData(
137 init='common.bsn_vport_q_in_q()',
138 pack='%s.pack()',
139 unpack='common.bsn_vport_q_in_q.unpack(%s)'),
140
141 ## TLV Lists
142
143 'list(of_action_t)': OFTypeData(
144 init='[]',
145 pack='util.pack_list(%s)',
146 unpack='action.unpack_list(%s)'),
147
148 'list(of_table_features_t)': OFTypeData(
149 init='[]',
150 pack='util.pack_list(%s)',
151 unpack=None),
152
153 'list(of_flow_stats_entry_t)': OFTypeData(
154 init='[]',
155 pack='util.pack_list(%s)',
156 unpack='common.unpack_list_flow_stats_entry(%s)'),
157
158 'list(of_bucket_t)': OFTypeData(
159 init='[]',
160 pack='util.pack_list(%s)',
161 unpack='common.unpack_list_bucket(%s)'),
162
163 'list(of_packet_queue_t)': OFTypeData(
164 init='[]',
165 pack='util.pack_list(%s)',
166 unpack='common.unpack_list_packet_queue(%s)'),
167
168 'list(of_meter_stats_t)': OFTypeData(
169 init='[]',
170 pack='util.pack_list(%s)',
171 unpack='common.unpack_list_meter_stats(%s)'),
172
173 # HACK need the match_v3 length field
174 'list(of_oxm_t)': OFTypeData(
175 init='[]',
176 pack='util.pack_list(%s)',
177 unpack='oxm.unpack_list(%s.slice(_length-4))'),
178
179 'list(of_group_stats_entry_t)': OFTypeData(
180 init='[]',
181 pack='util.pack_list(%s)',
182 unpack='common.unpack_list_group_stats_entry(%s)'),
183
184 'list(of_hello_elem_t)': OFTypeData(
185 init='[]',
186 pack='util.pack_list(%s)',
187 unpack='common.unpack_list_hello_elem(%s)'),
188
189 'list(of_action_id_t)': OFTypeData(
190 init='[]',
191 pack='util.pack_list(%s)',
192 unpack=None),
193
194 'list(of_group_desc_stats_entry_t)': OFTypeData(
195 init='[]',
196 pack='util.pack_list(%s)',
197 unpack='common.unpack_list_group_desc_stats_entry(%s)'),
198
199 'list(of_queue_prop_t)': OFTypeData(
200 init='[]',
201 pack='util.pack_list(%s)',
202 unpack='common.unpack_list_queue_prop(%s)'),
203
204 'list(of_instruction_t)': OFTypeData(
205 init='[]',
206 pack='util.pack_list(%s)',
207 unpack='instruction.unpack_list(%s)'),
208
209 'list(of_table_feature_prop_t)': OFTypeData(
210 init='[]',
211 pack='util.pack_list(%s)',
212 unpack=None),
213
214 'list(of_meter_band_t)': OFTypeData(
215 init='[]',
216 pack='util.pack_list(%s)',
217 unpack='meter_band.unpack_list(%s)'),
218
219 ## Lists with fixed-length elements
220
221 'list(of_bucket_counter_t)': OFTypeData(
222 init='[]',
223 pack='util.pack_list(%s)',
224 unpack='loxi.generic_util.unpack_list(%s, common.bucket_counter.unpack)'),
225
226 'list(of_uint32_t)': OFTypeData(
227 init='[]',
228 pack='util.pack_list(%s)',
229 unpack='loxi.generic_util.unpack_list(%s, common.uint32.unpack)'),
230
231 'list(of_queue_stats_entry_t)': OFTypeData(
232 init='[]',
233 pack='util.pack_list(%s)',
234 unpack='loxi.generic_util.unpack_list(%s, common.queue_stats_entry.unpack)'),
235
236 'list(of_table_stats_entry_t)': OFTypeData(
237 init='[]',
238 pack='util.pack_list(%s)',
239 unpack='loxi.generic_util.unpack_list(%s, common.table_stats_entry.unpack)'),
240
241 'list(of_uint8_t)': OFTypeData(
242 init='[]',
243 pack='util.pack_list(%s)',
244 unpack='loxi.generic_util.unpack_list(%s, common.uint8.unpack)'),
245
246 'list(of_port_stats_entry_t)': OFTypeData(
247 init='[]',
248 pack='util.pack_list(%s)',
249 unpack='loxi.generic_util.unpack_list(%s, common.port_stats_entry.unpack)'),
250
251 'list(of_bsn_interface_t)': OFTypeData(
252 init='[]',
253 pack='util.pack_list(%s)',
254 unpack='loxi.generic_util.unpack_list(%s, common.bsn_interface.unpack)'),
255
256 'list(of_meter_band_stats_t)': OFTypeData(
257 init='[]',
258 pack='util.pack_list(%s)',
259 unpack='loxi.generic_util.unpack_list(%s, common.meter_band_stats.unpack)'),
260
261 'list(of_port_desc_t)': OFTypeData(
262 init='[]',
263 pack='util.pack_list(%s)',
264 unpack='loxi.generic_util.unpack_list(%s, common.port_desc.unpack)'),
265}
Rich Lanea06d0c32013-03-25 08:52:03 -0700266
267class OFType(object):
268 """
269 Encapsulates knowledge about the OpenFlow type system.
270 """
271
272 version = None
273 base = None
Rich Lanea06d0c32013-03-25 08:52:03 -0700274
275 def __init__(self, string, version):
276 self.version = version
Rich Lane8a22cda2013-06-19 13:20:07 -0700277 self.base = string
278 self.type_data = type_data.get(self.base)
Rich Lanea06d0c32013-03-25 08:52:03 -0700279
280 def gen_init_expr(self):
Rich Lane8a22cda2013-06-19 13:20:07 -0700281 if self.type_data and self.type_data.init:
282 return self.type_data.init
Rich Lanea06d0c32013-03-25 08:52:03 -0700283 else:
Rich Lane8a22cda2013-06-19 13:20:07 -0700284 return "loxi.unimplemented('init %s')" % self.base
Rich Lanea06d0c32013-03-25 08:52:03 -0700285
Rich Lane8a22cda2013-06-19 13:20:07 -0700286 def gen_pack_expr(self, value_expr):
287 if self.type_data and self.type_data.pack:
288 return self.type_data.pack % value_expr
Rich Lanea06d0c32013-03-25 08:52:03 -0700289 else:
Rich Lane8a22cda2013-06-19 13:20:07 -0700290 "loxi.unimplemented('pack %s')" % self.base
Rich Lanea06d0c32013-03-25 08:52:03 -0700291
Rich Lane57026dc2013-05-01 10:13:16 -0700292 def gen_unpack_expr(self, reader_expr):
Rich Lane8a22cda2013-06-19 13:20:07 -0700293 if self.type_data and self.type_data.unpack:
294 return self.type_data.unpack % reader_expr
Rich Lanea06d0c32013-03-25 08:52:03 -0700295 else:
Rich Lane8a22cda2013-06-19 13:20:07 -0700296 "loxi.unimplemented('unpack %s')" % self.base