blob: 06161ec373b27f7188b9efc914dd84ae0436e701 [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
28##
29# @brief C code generation for LOXI type related maps
30#
31
Andreas Wundsam76db0062013-11-15 13:34:41 -080032import c_gen.of_g_legacy as of_g
Rich Lanea06d0c32013-03-25 08:52:03 -070033import sys
34from generic_utils import *
Andreas Wundsam542a13c2013-11-15 13:28:55 -080035import c_gen.type_maps as type_maps
Rich Lanea06d0c32013-03-25 08:52:03 -070036
37
38# Some number larger than small type values, but less then
39# reserved values like 0xffff
40max_type_value = 1000
41
Rich Lanea06d0c32013-03-25 08:52:03 -070042def gen_type_to_object_id(out, type_str, prefix, template,
43 value_array, max_val):
44 """
45 Generate C maps from various message class groups to object ids
46
47 For each version, create an array mapping the type info to the
48 object ID. Then define an array containing those pointers.
49 """
50
51 # Create unified arrays and get length
52 arr_len = type_maps.type_array_len(value_array, max_val)
53 all_ars = []
54 for version, val_dict in value_array.items(): # Per version dict
55 ar = type_maps.dict_to_array(val_dict, max_val, type_maps.invalid_type)
56 all_ars.append(ar)
57
58 len_name = "%s_ITEM_COUNT" % prefix
59
60 for i, ar in enumerate(all_ars):
61 version = i + 1
Rich Laneb157b0f2013-03-27 13:55:28 -070062 out.write("static const of_object_id_t\nof_%s_v%d[%s] = {\n" %
Rich Lanea06d0c32013-03-25 08:52:03 -070063 (type_str, version, len_name))
64 for i in range(arr_len):
65 comma = ""
66 if i < arr_len - 1: # Avoid ultimate comma
67 comma = ","
68
69 # Per-version length check
70 if i < len(ar):
71 v = ar[i]
72 else:
73 v = type_maps.invalid_type
74
75 if v == type_maps.invalid_type:
76 out.write(" %-30s /* %d (Invalid) */\n" %
77 ("OF_OBJECT_INVALID" + comma, i))
78 else:
79 name = (template % v.upper()) + comma
80 out.write(" %-30s /* %d */\n" % (name, i))
81 out.write("};\n")
82
83 out.write("""
84/**
85 * Maps from %(c_name)s wire type values to LOCI object ids
86 *
87 * Indexed by wire version which is 1-based.
88 */
89
Rich Laneb157b0f2013-03-27 13:55:28 -070090const of_object_id_t *const of_%(name)s[OF_VERSION_ARRAY_MAX] = {
Rich Lanea06d0c32013-03-25 08:52:03 -070091 NULL,
92""" % dict(name=type_str, c_name=prefix.lower()))
93 for version in of_g.of_version_range:
94 out.write(" of_%(name)s_v%(version)d,\n" % dict(name=type_str,
95 version=version))
96 out.write("""
97};
98
Andreas Wundsam53256162013-05-02 14:05:53 -070099""" % dict(name=type_str, u_name=type_str.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700100 max_val=max_val, c_name=prefix.lower()))
101
102def gen_type_maps(out):
103 """
104 Generate various type maps
105 @param out The file handle to write to
106 """
107
Rich Lanea06d0c32013-03-25 08:52:03 -0700108 # Generate maps from wire type values to object IDs
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700109 gen_type_to_object_id(out, "error_msg_type_to_id", "OF_ERROR_MSG",
110 "OF_%s_ERROR_MSG", type_maps.error_types,
111 max_type_value)
Rich Lanea06d0c32013-03-25 08:52:03 -0700112 gen_type_to_object_id(out, "action_type_to_id", "OF_ACTION",
113 "OF_ACTION_%s", type_maps.action_types,
114 max_type_value)
115 gen_type_to_object_id(out, "action_id_type_to_id", "OF_ACTION_ID",
116 "OF_ACTION_ID_%s", type_maps.action_id_types,
117 max_type_value)
118 gen_type_to_object_id(out, "instruction_type_to_id", "OF_INSTRUCTION",
Andreas Wundsam53256162013-05-02 14:05:53 -0700119 "OF_INSTRUCTION_%s", type_maps.instruction_types,
Rich Lanea06d0c32013-03-25 08:52:03 -0700120 max_type_value)
121 gen_type_to_object_id(out, "queue_prop_type_to_id", "OF_QUEUE_PROP",
122 "OF_QUEUE_PROP_%s", type_maps.queue_prop_types,
123 max_type_value)
124 gen_type_to_object_id(out, "table_feature_prop_type_to_id",
125 "OF_TABLE_FEATURE_PROP",
126 "OF_TABLE_FEATURE_PROP_%s",
127 type_maps.table_feature_prop_types,
128 max_type_value)
129 gen_type_to_object_id(out, "meter_band_type_to_id", "OF_METER_BAND",
130 "OF_METER_BAND_%s", type_maps.meter_band_types,
131 max_type_value)
132 gen_type_to_object_id(out, "hello_elem_type_to_id", "OF_HELLO_ELEM",
133 "OF_HELLO_ELEM_%s", type_maps.hello_elem_types,
134 max_type_value)
Rich Lanee3113672013-12-06 17:09:57 -0800135 gen_type_to_object_id(out, "group_mod_type_to_id", "OF_GROUP_MOD",
136 "OF_GROUP_%s", type_maps.group_mod_types,
137 max_type_value)
Rich Lanea06d0c32013-03-25 08:52:03 -0700138
139 # FIXME: Multipart re-organization
140 gen_type_to_object_id(out, "stats_request_type_to_id", "OF_STATS_REQUEST",
141 "OF_%s_STATS_REQUEST", type_maps.stats_types,
142 max_type_value)
143 gen_type_to_object_id(out, "stats_reply_type_to_id", "OF_STATS_REPLY",
144 "OF_%s_STATS_REPLY", type_maps.stats_types,
145 max_type_value)
146 gen_type_to_object_id(out, "flow_mod_type_to_id", "OF_FLOW_MOD",
147 "OF_FLOW_%s", type_maps.flow_mod_types,
148 max_type_value)
149 gen_type_to_object_id(out, "oxm_type_to_id", "OF_OXM",
150 "OF_OXM_%s", type_maps.oxm_types, max_type_value)
151 gen_type_to_object_id(out, "message_type_to_id", "OF_MESSAGE",
152 "OF_%s", type_maps.message_types, max_type_value)
153
Rich Lanea06d0c32013-03-25 08:52:03 -0700154def gen_type_to_obj_map_functions(out):
155 """
Rich Lanec0e20ff2013-12-15 23:40:31 -0800156 Generate the templated type map functions
Rich Lanea06d0c32013-03-25 08:52:03 -0700157 @param out The file handle to write to
158 """
159
160 ################################################################
161 # Generate all type-to-object-ID maps in a common way
162 ################################################################
163 map_template = """
164/**
165 * %(name)s wire type to object ID array.
166 * Treat as private; use function accessor below
167 */
168
Rich Laneb157b0f2013-03-27 13:55:28 -0700169extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];
Rich Lanea06d0c32013-03-25 08:52:03 -0700170
171#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n
172
173/**
174 * Map an %(name)s wire value to an OF object
175 * @param %(name)s The %(name)s type wire value
176 * @param version The version associated with the check
177 * @return The %(name)s OF object type
178 * @return OF_OBJECT_INVALID if type does not map to an object
Andreas Wundsam53256162013-05-02 14:05:53 -0700179 *
Rich Lanea06d0c32013-03-25 08:52:03 -0700180 */
Rich Lanec0e20ff2013-12-15 23:40:31 -0800181of_object_id_t
Andreas Wundsam53256162013-05-02 14:05:53 -0700182of_%(name)s_to_object_id(int %(name)s, of_version_t version)
Rich Lanea06d0c32013-03-25 08:52:03 -0700183{
184 if (!OF_VERSION_OKAY(version)) {
185 return OF_OBJECT_INVALID;
186 }
187 if (%(name)s < 0 || %(name)s >= OF_%(u_name)s_ITEM_COUNT) {
188 return OF_OBJECT_INVALID;
189 }
190
191 return of_%(name)s_type_to_id[version][%(name)s];
192}
193"""
194 map_with_experimenter_template = """
195/**
196 * %(name)s wire type to object ID array.
197 * Treat as private; use function accessor below
198 */
199
Rich Laneb157b0f2013-03-27 13:55:28 -0700200extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];
Rich Lanea06d0c32013-03-25 08:52:03 -0700201
202#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n
203
204/**
205 * Map an %(name)s wire value to an OF object
206 * @param %(name)s The %(name)s type wire value
207 * @param version The version associated with the check
208 * @return The %(name)s OF object type
209 * @return OF_OBJECT_INVALID if type does not map to an object
Andreas Wundsam53256162013-05-02 14:05:53 -0700210 *
Rich Lanea06d0c32013-03-25 08:52:03 -0700211 */
Rich Lanec0e20ff2013-12-15 23:40:31 -0800212of_object_id_t
Andreas Wundsam53256162013-05-02 14:05:53 -0700213of_%(name)s_to_object_id(int %(name)s, of_version_t version)
Rich Lanea06d0c32013-03-25 08:52:03 -0700214{
215 if (!OF_VERSION_OKAY(version)) {
216 return OF_OBJECT_INVALID;
217 }
218 if (%(name)s == OF_EXPERIMENTER_TYPE) {
219 return OF_%(u_name)s_EXPERIMENTER;
220 }
221 if (%(name)s < 0 || %(name)s >= OF_%(u_name)s_ITEM_COUNT) {
222 return OF_OBJECT_INVALID;
223 }
224
225 return of_%(name)s_type_to_id[version][%(name)s];
226}
227"""
228
229 stats_template = """
230/**
231 * %(name)s wire type to object ID array.
232 * Treat as private; use function accessor below
233 */
234
Rich Laneb157b0f2013-03-27 13:55:28 -0700235extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];
Rich Lanea06d0c32013-03-25 08:52:03 -0700236
237#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n
238
239/**
240 * Map an %(name)s wire value to an OF object
241 * @param %(name)s The %(name)s type wire value
242 * @param version The version associated with the check
243 * @return The %(name)s OF object type
244 * @return OF_OBJECT_INVALID if type does not map to an object
Andreas Wundsam53256162013-05-02 14:05:53 -0700245 *
Rich Lanea06d0c32013-03-25 08:52:03 -0700246 */
Rich Lanec0e20ff2013-12-15 23:40:31 -0800247of_object_id_t
Andreas Wundsam53256162013-05-02 14:05:53 -0700248of_%(name)s_to_object_id(int %(name)s, of_version_t version)
Rich Lanea06d0c32013-03-25 08:52:03 -0700249{
250 if (!OF_VERSION_OKAY(version)) {
251 return OF_OBJECT_INVALID;
252 }
253 if (%(name)s == OF_EXPERIMENTER_TYPE) {
254 return OF_EXPERIMENTER_%(u_name)s;
255 }
256 if (%(name)s < 0 || %(name)s >= OF_%(u_name)s_ITEM_COUNT) {
257 return OF_OBJECT_INVALID;
258 }
259
260 return of_%(name)s_type_to_id[version][%(name)s];
261}
262"""
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700263
264 error_msg_template = """
265/**
266 * %(name)s wire type to object ID array.
267 * Treat as private; use function accessor below
268 */
269
270extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];
271
272#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n
273
274/**
275 * Map an %(name)s wire value to an OF object
276 * @param %(name)s The %(name)s type wire value
277 * @param version The version associated with the check
278 * @return The %(name)s OF object type
279 * @return OF_OBJECT_INVALID if type does not map to an object
280 *
281 */
Rich Lanec0e20ff2013-12-15 23:40:31 -0800282of_object_id_t
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700283of_error_msg_to_object_id(uint16_t %(name)s, of_version_t version)
284{
285 if (!OF_VERSION_OKAY(version)) {
286 return OF_OBJECT_INVALID;
287 }
288 if (%(name)s == OF_EXPERIMENTER_TYPE) {
289 return OF_EXPERIMENTER_ERROR_MSG;
290 }
291 if (%(name)s < 0 || %(name)s >= OF_%(u_name)s_ITEM_COUNT) {
292 return OF_OBJECT_INVALID;
293 }
294
295 return of_%(name)s_type_to_id[version][%(name)s];
296}
297"""
298
Rich Lanea06d0c32013-03-25 08:52:03 -0700299 # Experimenter mapping functions
300 # Currently we support very few candidates, so we just do a
301 # list of if/elses
302 experimenter_function = """
303/**
304 * @brief Map a message known to be an exp msg to the proper object
305 *
306 * Assume that the message is a vendor/experimenter message. Determine
307 * the specific object type for the message.
308 * @param msg An OF message object (uint8_t *)
309 * @param length The number of bytes in the message (for error checking)
310 * @param version Version of message
311 * @returns object ID of specific type if recognized or OF_EXPERIMENTER if not
312 *
313 * @todo put OF_EXPERIMENTER_<name> in loci_base.h
314 */
315
Rich Lanec0e20ff2013-12-15 23:40:31 -0800316of_object_id_t
Rich Lanea06d0c32013-03-25 08:52:03 -0700317of_message_experimenter_to_object_id(of_message_t msg, of_version_t version) {
318 uint32_t experimenter_id;
319 uint32_t subtype;
320
321 /* Extract experimenter and subtype value; look for match from type maps */
322 experimenter_id = of_message_experimenter_id_get(msg);
323 subtype = of_message_experimenter_subtype_get(msg);
324
325 /* Do a simple if/else search for the ver, experimenter and subtype */
326"""
327 first = True
328 for version, experimenter_lists in type_maps.extension_message_subtype.items():
329 for exp, subtypes in experimenter_lists.items():
330 experimenter_function += """
Andreas Wundsam53256162013-05-02 14:05:53 -0700331 if ((experimenter_id == OF_EXPERIMENTER_ID_%(exp_name)s) &&
Rich Lanea06d0c32013-03-25 08:52:03 -0700332 (version == %(ver_name)s)) {
333""" % dict(exp_name=exp.upper(), ver_name=of_g.wire_ver_map[version])
334 for ext_msg, subtype in subtypes.items():
335 experimenter_function += """
336 if (subtype == %(subtype)s) {
337 return %(ext_msg)s;
338 }
339""" % dict(subtype=subtype, ext_msg=ext_msg.upper())
340 experimenter_function += """
341 }
342"""
343 experimenter_function += """
344 return OF_EXPERIMENTER;
345}
346"""
347
348 # Message need different handling
349 msg_template = """
350/**
351 * %(name)s wire type to object ID array.
352 * Treat as private; use function accessor below
353 */
354
Rich Laneb157b0f2013-03-27 13:55:28 -0700355extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];
Rich Lanea06d0c32013-03-25 08:52:03 -0700356
357#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n
358
359/**
360 * Extract the type info from the message and determine its object type
361 * @param msg An OF message object (uint8_t *)
362 * @param length The number of bytes in the message (for error checking)
363 * @returns object ID or OF_OBJECT_INVALID if parse error
364 */
365
Rich Lanec0e20ff2013-12-15 23:40:31 -0800366of_object_id_t
Rich Lanea06d0c32013-03-25 08:52:03 -0700367of_message_to_object_id(of_message_t msg, int length) {
368 uint8_t type;
369 of_version_t ver;
370 of_object_id_t obj_id;
371 uint16_t stats_type;
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700372 uint16_t err_type;
Rich Lanea06d0c32013-03-25 08:52:03 -0700373 uint8_t flow_mod_cmd;
Rich Lane353a79f2013-11-13 10:39:56 -0800374 uint32_t experimenter, subtype;
Rich Lanee3113672013-12-06 17:09:57 -0800375 uint16_t group_mod_cmd;
Rich Lanea06d0c32013-03-25 08:52:03 -0700376
377 if (length < OF_MESSAGE_MIN_LENGTH) {
378 return OF_OBJECT_INVALID;
379 }
380 type = of_message_type_get(msg);
381 ver = of_message_version_get(msg);
382 if (!OF_VERSION_OKAY(ver)) {
383 return OF_OBJECT_INVALID;
384 }
385
386 if (type >= OF_MESSAGE_ITEM_COUNT) {
387 return OF_OBJECT_INVALID;
388 }
389
390 obj_id = of_message_type_to_id[ver][type];
391
392 /* Remap to specific message if known */
393 if (obj_id == OF_EXPERIMENTER) {
394 if (length < OF_MESSAGE_EXPERIMENTER_MIN_LENGTH) {
395 return OF_OBJECT_INVALID;
396 }
397 return of_message_experimenter_to_object_id(msg, ver);
398 }
399
400 /* Remap to add/delete/strict version */
401 if (obj_id == OF_FLOW_MOD) {
402 if (length < OF_MESSAGE_MIN_FLOW_MOD_LENGTH(ver)) {
403 return OF_OBJECT_INVALID;
404 }
405 flow_mod_cmd = of_message_flow_mod_command_get(msg, ver);
406 obj_id = of_flow_mod_to_object_id(flow_mod_cmd, ver);
407 }
408
409 if ((obj_id == OF_STATS_REQUEST) || (obj_id == OF_STATS_REPLY)) {
410 if (length < OF_MESSAGE_MIN_STATS_LENGTH) {
411 return OF_OBJECT_INVALID;
412 }
413 stats_type = of_message_stats_type_get(msg);
Rich Lane353a79f2013-11-13 10:39:56 -0800414 if (stats_type == OF_STATS_TYPE_EXPERIMENTER) {
415 if (length < OF_MESSAGE_STATS_EXPERIMENTER_MIN_LENGTH) {
416 return OF_OBJECT_INVALID;
417 }
418 experimenter = of_message_stats_experimenter_id_get(msg);
419 subtype = of_message_stats_experimenter_subtype_get(msg);
420 if (obj_id == OF_STATS_REQUEST) {
421 obj_id = of_experimenter_stats_request_to_object_id(experimenter, subtype, ver);
422 } else {
423 obj_id = of_experimenter_stats_reply_to_object_id(experimenter, subtype, ver);
424 }
Rich Lanea06d0c32013-03-25 08:52:03 -0700425 } else {
Rich Lane353a79f2013-11-13 10:39:56 -0800426 if (obj_id == OF_STATS_REQUEST) {
427 obj_id = of_stats_request_to_object_id(stats_type, ver);
428 } else {
429 obj_id = of_stats_reply_to_object_id(stats_type, ver);
430 }
Rich Lanea06d0c32013-03-25 08:52:03 -0700431 }
432 }
433
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700434 if (obj_id == OF_ERROR_MSG) {
435 if (length < OF_MESSAGE_MIN_ERROR_LENGTH) {
436 return OF_OBJECT_INVALID;
437 }
438 err_type = of_message_error_type_get(msg);
439 obj_id = of_error_msg_to_object_id(err_type, ver);
440 }
441
Rich Lanee3113672013-12-06 17:09:57 -0800442 if (obj_id == OF_GROUP_MOD) {
443 if (length < OF_MESSAGE_MIN_GROUP_MOD_LENGTH) {
444 return OF_OBJECT_INVALID;
445 }
446 group_mod_cmd = of_message_group_mod_command_get(msg);
447 obj_id = of_group_mod_to_object_id(group_mod_cmd, ver);
448 }
449
Rich Lanea06d0c32013-03-25 08:52:03 -0700450 return obj_id;
451}
452"""
453
Rich Laned8d29c92013-09-24 13:46:42 -0700454 oxm_template = """
455/**
456 * oxm wire type to object ID array.
457 * Treat as private; use function accessor below
458 */
459
460extern const of_object_id_t *const of_oxm_type_to_id[OF_VERSION_ARRAY_MAX];
461
462#define OF_OXM_ITEM_COUNT %(ar_len)d\n
463
464/**
465 * Map an oxm wire value to an OF object
466 * @param oxm The oxm type wire value
467 * @param version The version associated with the check
468 * @return The oxm OF object type
469 * @return OF_OBJECT_INVALID if type does not map to an object
470 *
471 */
Rich Lanec0e20ff2013-12-15 23:40:31 -0800472of_object_id_t
Rich Laned8d29c92013-09-24 13:46:42 -0700473of_oxm_to_object_id(uint32_t type_len, of_version_t version)
474{
475 if (!OF_VERSION_OKAY(version)) {
476 return OF_OBJECT_INVALID;
477 }
478
479 uint16_t class = (type_len >> 16) & 0xffff;
480 uint8_t masked_type = (type_len >> 8) & 0xff;
481
482 if (class == 0x8000) {
483 if (masked_type < 0 || masked_type >= OF_OXM_ITEM_COUNT) {
484 return OF_OBJECT_INVALID;
485 }
486
487 return of_oxm_type_to_id[version][masked_type];
488 } else if (class == 0x0003) {
489 switch (masked_type) {
490 case 0x00: return OF_OXM_BSN_IN_PORTS_128;
491 case 0x01: return OF_OXM_BSN_IN_PORTS_128_MASKED;
Rich Lane61718362013-10-24 16:59:42 -0700492 case 0x02: return OF_OXM_BSN_LAG_ID;
493 case 0x03: return OF_OXM_BSN_LAG_ID_MASKED;
Rich Laneeb21c4f2013-10-28 17:34:41 -0700494 case 0x04: return OF_OXM_BSN_VRF;
495 case 0x05: return OF_OXM_BSN_VRF_MASKED;
496 case 0x06: return OF_OXM_BSN_GLOBAL_VRF_ALLOWED;
497 case 0x07: return OF_OXM_BSN_GLOBAL_VRF_ALLOWED_MASKED;
498 case 0x08: return OF_OXM_BSN_L3_INTERFACE_CLASS_ID;
499 case 0x09: return OF_OXM_BSN_L3_INTERFACE_CLASS_ID_MASKED;
500 case 0x0a: return OF_OXM_BSN_L3_SRC_CLASS_ID;
501 case 0x0b: return OF_OXM_BSN_L3_SRC_CLASS_ID_MASKED;
502 case 0x0c: return OF_OXM_BSN_L3_DST_CLASS_ID;
503 case 0x0d: return OF_OXM_BSN_L3_DST_CLASS_ID_MASKED;
Rich Laned8d29c92013-09-24 13:46:42 -0700504 default: return OF_OBJECT_INVALID;
505 }
506 } else {
507 return OF_OBJECT_INVALID;
508 }
509}
510"""
511
Rich Lanea06d0c32013-03-25 08:52:03 -0700512 # Action types array gen
513 ar_len = type_maps.type_array_len(type_maps.action_types, max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700514 out.write(map_with_experimenter_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700515 dict(name="action", u_name="ACTION", ar_len=ar_len))
516
517 # Action ID types array gen
518 ar_len = type_maps.type_array_len(type_maps.action_id_types, max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700519 out.write(map_with_experimenter_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700520 dict(name="action_id", u_name="ACTION_ID", ar_len=ar_len))
521
522 # Instruction types array gen
523 ar_len = type_maps.type_array_len(type_maps.instruction_types,
524 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700525 out.write(map_with_experimenter_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700526 dict(name="instruction", u_name="INSTRUCTION", ar_len=ar_len))
527
528 # Queue prop types array gen
529 ar_len = type_maps.type_array_len(type_maps.queue_prop_types,
530 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700531 out.write(map_with_experimenter_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700532 dict(name="queue_prop", u_name="QUEUE_PROP", ar_len=ar_len))
533
534 # Table feature prop types array gen
535 ar_len = type_maps.type_array_len(type_maps.table_feature_prop_types,
536 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700537 out.write(map_with_experimenter_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700538 dict(name="table_feature_prop", u_name="TABLE_FEATURE_PROP",
539 ar_len=ar_len))
540
541 # Meter band types array gen
542 ar_len = type_maps.type_array_len(type_maps.meter_band_types,
543 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700544 out.write(map_with_experimenter_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700545 dict(name="meter_band", u_name="METER_BAND", ar_len=ar_len))
546
547 # Hello elem types array gen
548 ar_len = type_maps.type_array_len(type_maps.hello_elem_types,
549 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700550 out.write(map_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700551 dict(name="hello_elem", u_name="HELLO_ELEM", ar_len=ar_len))
552
553 # Stats types array gen
554 ar_len = type_maps.type_array_len(type_maps.stats_types,
555 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700556 out.write(stats_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700557 dict(name="stats_reply", u_name="STATS_REPLY", ar_len=ar_len))
Andreas Wundsam53256162013-05-02 14:05:53 -0700558 out.write(stats_template %
559 dict(name="stats_request", u_name="STATS_REQUEST",
Rich Lanea06d0c32013-03-25 08:52:03 -0700560 ar_len=ar_len))
561
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700562 ar_len = type_maps.type_array_len(type_maps.error_types,
563 max_type_value)
564 out.write(error_msg_template %
565 dict(name="error_msg", u_name="ERROR_MSG", ar_len=ar_len))
566# out.write(error_msg_function)
567
Rich Lanea06d0c32013-03-25 08:52:03 -0700568 ar_len = type_maps.type_array_len(type_maps.flow_mod_types, max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700569 out.write(map_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700570 dict(name="flow_mod", u_name="FLOW_MOD", ar_len=ar_len))
571
Rich Lanee3113672013-12-06 17:09:57 -0800572 ar_len = type_maps.type_array_len(type_maps.group_mod_types,
573 max_type_value)
574 out.write(map_template %
575 dict(name="group_mod", u_name="GROUP_MOD", ar_len=ar_len))
576
Rich Laned8d29c92013-09-24 13:46:42 -0700577 # OXM
Rich Lanea06d0c32013-03-25 08:52:03 -0700578 ar_len = type_maps.type_array_len(type_maps.oxm_types, max_type_value)
579 out.write("""
580/* NOTE: We could optimize the OXM and only generate OF 1.2 versions. */
581""")
Rich Laned8d29c92013-09-24 13:46:42 -0700582 out.write(oxm_template % dict(ar_len=ar_len))
Rich Lanea06d0c32013-03-25 08:52:03 -0700583
Rich Laned8d29c92013-09-24 13:46:42 -0700584 # Messages
Rich Lanea06d0c32013-03-25 08:52:03 -0700585 out.write(experimenter_function)
586 # Must follow stats reply/request
587 ar_len = type_maps.type_array_len(type_maps.message_types, max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700588 out.write(msg_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700589 dict(name="message", u_name="MESSAGE", ar_len=ar_len))
590
Rich Lanea06d0c32013-03-25 08:52:03 -0700591def gen_type_data_header(out):
592
593 out.write("""
594/****************************************************************
595 *
596 * The following declarations are for type and length calculations.
597 * Implementations may be found in of_type_maps.c
598 *
599 ****************************************************************/
600/*
601 * Special case length functions for objects with
602 */
603""")
604 for ((cls, name), prev) in of_g.special_offsets.items():
605 s_cls = cls[3:] # take off of_
606 out.write("""
607/**
608 * Special length calculation for %(cls)s->%(name)s.
Andreas Wundsam53256162013-05-02 14:05:53 -0700609 * @param obj An object of type %(cls)s to check for
Rich Lanea06d0c32013-03-25 08:52:03 -0700610 * length of %(name)s
611 * @param bytes[out] Where to store the calculated length
612 *
613 * Preceding data member is %(prev)s.
614 */
615extern int of_length_%(s_cls)s_%(name)s_get(
616 %(cls)s_t *obj, int *bytes);
617
618/**
619 * Special offset calculation for %(cls)s->%(name)s.
Andreas Wundsam53256162013-05-02 14:05:53 -0700620 * @param obj An object of type %(cls)s to check for
Rich Lanea06d0c32013-03-25 08:52:03 -0700621 * length of %(name)s
622 * @param offset[out] Where to store the calculated length
623 *
624 * Preceding data member is %(prev)s.
625 */
626extern int of_offset_%(s_cls)s_%(name)s_get(
627 %(cls)s_t *obj, int *offset);
628""" % dict(cls=cls, s_cls=s_cls, name=name, prev=prev))
629
630# NOT NEEDED YET
631# # For non-message, variable length objects, give a fun that
632# # calculates the length
633# for cls in of_g.standard_class_order:
634# s_cls = cls[3:] # take off of_
635# if !type_is_var_len(cls, version):
636# continue
637# out.write("""
638# /**
639# * Special length calculation for variable length object %(cls)s
640# * @param obj An object of type %(cls)s whose length is being calculated
641# * @param bytes[out] Where to store the calculated length
642# *
643# * The assumption is that the length member of the object is not
644# * valid and the length needs to be calculated from other information
645# * such as the parent.
646# */
647# extern int of_length_%(s_cls)s_get(
648# %(cls)s_t *obj, int *bytes);
Andreas Wundsam53256162013-05-02 14:05:53 -0700649# """ % dict(cls=cls, s_cls=s_cls))
Rich Lanea06d0c32013-03-25 08:52:03 -0700650
651 out.write("""
652/****************************************************************
653 * Wire type/length functions.
654 ****************************************************************/
655
656extern void of_object_message_wire_length_get(of_object_t *obj, int *bytes);
657extern void of_object_message_wire_length_set(of_object_t *obj, int bytes);
658
659extern void of_oxm_wire_length_get(of_object_t *obj, int *bytes);
Rich Lanea06d0c32013-03-25 08:52:03 -0700660extern void of_oxm_wire_object_id_get(of_object_t *obj, of_object_id_t *id);
Rich Lanea06d0c32013-03-25 08:52:03 -0700661
662extern void of_tlv16_wire_length_get(of_object_t *obj, int *bytes);
663extern void of_tlv16_wire_length_set(of_object_t *obj, int bytes);
664
Rich Lanea06d0c32013-03-25 08:52:03 -0700665/* Wire length is uint16 at front of structure */
666extern void of_u16_len_wire_length_get(of_object_t *obj, int *bytes);
667extern void of_u16_len_wire_length_set(of_object_t *obj, int bytes);
668
669extern void of_action_wire_object_id_get(of_object_t *obj, of_object_id_t *id);
670extern void of_action_id_wire_object_id_get(of_object_t *obj, of_object_id_t *id);
Andreas Wundsam53256162013-05-02 14:05:53 -0700671extern void of_instruction_wire_object_id_get(of_object_t *obj,
Rich Lanea06d0c32013-03-25 08:52:03 -0700672 of_object_id_t *id);
Andreas Wundsam53256162013-05-02 14:05:53 -0700673extern void of_queue_prop_wire_object_id_get(of_object_t *obj,
Rich Lanea06d0c32013-03-25 08:52:03 -0700674 of_object_id_t *id);
Andreas Wundsam53256162013-05-02 14:05:53 -0700675extern void of_table_feature_prop_wire_object_id_get(of_object_t *obj,
Rich Lanea06d0c32013-03-25 08:52:03 -0700676 of_object_id_t *id);
Andreas Wundsam53256162013-05-02 14:05:53 -0700677extern void of_meter_band_wire_object_id_get(of_object_t *obj,
Rich Lanea06d0c32013-03-25 08:52:03 -0700678 of_object_id_t *id);
Andreas Wundsam53256162013-05-02 14:05:53 -0700679extern void of_hello_elem_wire_object_id_get(of_object_t *obj,
Rich Lanea06d0c32013-03-25 08:52:03 -0700680 of_object_id_t *id);
681
Rich Lane47085722013-07-12 16:27:04 -0700682#define OF_OXM_LENGTH_GET(hdr) (((hdr) & 0xff) + 4)
Rich Lanea06d0c32013-03-25 08:52:03 -0700683#define OF_OXM_LENGTH_SET(hdr, val) \\
Rich Lane47085722013-07-12 16:27:04 -0700684 (hdr) = ((hdr) & 0xffffff00) + (((val) - 4) & 0xff)
Rich Lanea06d0c32013-03-25 08:52:03 -0700685
686extern void of_packet_queue_wire_length_get(of_object_t *obj, int *bytes);
687extern void of_packet_queue_wire_length_set(of_object_t *obj, int bytes);
688
689extern void of_list_meter_band_stats_wire_length_get(of_object_t *obj,
690 int *bytes);
691extern void of_meter_stats_wire_length_get(of_object_t *obj, int *bytes);
692extern void of_meter_stats_wire_length_set(of_object_t *obj, int bytes);
693extern int of_extension_object_wire_push(of_object_t *obj);
694
695""")
696
697
698def gen_length_array(out):
699 """
700 Generate an array giving the lengths of all objects/versions
701 @param out The file handle to which to write
702 """
703 out.write("""
704/**
705 * An array with the number of bytes in the fixed length part
706 * of each OF object
707 */
708""")
709
710 for version in of_g.of_version_range:
711 out.write("""
Rich Laneb157b0f2013-03-27 13:55:28 -0700712static const int\nof_object_fixed_len_v%d[OF_OBJECT_COUNT] = {
Rich Lanea06d0c32013-03-25 08:52:03 -0700713 -1, /* of_object is not instantiable */
714""" % version)
715 for i, cls in enumerate(of_g.all_class_order):
716 comma = ","
717 if i == len(of_g.all_class_order) - 1:
718 comma = ""
719 val = "-1" + comma
720 if (cls, version) in of_g.base_length:
721 val = str(of_g.base_length[(cls, version)]) + comma
722 out.write(" %-5s /* %d: %s */\n" % (val, i + 1, cls))
723 out.write("};\n")
724
725 out.write("""
726/**
727 * Unified map of fixed length part of each object
728 */
Rich Laneb157b0f2013-03-27 13:55:28 -0700729const int *const of_object_fixed_len[OF_VERSION_ARRAY_MAX] = {
Rich Lanea06d0c32013-03-25 08:52:03 -0700730 NULL,
731""")
732 for version in of_g.of_version_range:
733 out.write(" of_object_fixed_len_v%d,\n" % version)
734 out.write("""
735};
736""")
737
Andreas Wundsam53256162013-05-02 14:05:53 -0700738
Rich Lanef70be942013-07-18 13:33:14 -0700739def gen_extra_length_array(out):
740 """
741 Generate an array giving the extra lengths of all objects/versions
742 @param out The file handle to which to write
743 """
744 out.write("""
745/**
746 * An array with the number of bytes in the extra length part
747 * of each OF object
748 */
749""")
750
751 for version in of_g.of_version_range:
752 out.write("""
753static const int\nof_object_extra_len_v%d[OF_OBJECT_COUNT] = {
754 -1, /* of_object is not instantiable */
755""" % version)
756 for i, cls in enumerate(of_g.all_class_order):
757 comma = ","
758 if i == len(of_g.all_class_order) - 1:
759 comma = ""
760 val = "-1" + comma
761 if (cls, version) in of_g.base_length:
762 val = str(of_g.extra_length.get((cls, version), 0)) + comma
763 out.write(" %-5s /* %d: %s */\n" % (val, i + 1, cls))
764 out.write("};\n")
765
766 out.write("""
767/**
768 * Unified map of extra length part of each object
769 */
770const int *const of_object_extra_len[OF_VERSION_ARRAY_MAX] = {
771 NULL,
772""")
773 for version in of_g.of_version_range:
774 out.write(" of_object_extra_len_v%d,\n" % version)
775 out.write("""
776};
777""")