blob: d4525ba1d7f85c4ec3608d35eb5d9bf9ba1ad25f [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 Lane713d9282013-12-30 15:21:35 -0800154 gen_type_to_object_id(out, "bsn_tlv_type_to_id", "OF_BSN_TLV",
155 "OF_BSN_TLV_%s", type_maps.bsn_tlv_types,
156 max_type_value)
157
Rich Lanea06d0c32013-03-25 08:52:03 -0700158def gen_type_to_obj_map_functions(out):
159 """
Rich Lanec0e20ff2013-12-15 23:40:31 -0800160 Generate the templated type map functions
Rich Lanea06d0c32013-03-25 08:52:03 -0700161 @param out The file handle to write to
162 """
163
164 ################################################################
165 # Generate all type-to-object-ID maps in a common way
166 ################################################################
167 map_template = """
168/**
169 * %(name)s wire type to object ID array.
170 * Treat as private; use function accessor below
171 */
172
Rich Laneb157b0f2013-03-27 13:55:28 -0700173extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];
Rich Lanea06d0c32013-03-25 08:52:03 -0700174
175#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n
176
177/**
178 * Map an %(name)s wire value to an OF object
179 * @param %(name)s The %(name)s type wire value
180 * @param version The version associated with the check
181 * @return The %(name)s OF object type
182 * @return OF_OBJECT_INVALID if type does not map to an object
Andreas Wundsam53256162013-05-02 14:05:53 -0700183 *
Rich Lanea06d0c32013-03-25 08:52:03 -0700184 */
Rich Lanec0e20ff2013-12-15 23:40:31 -0800185of_object_id_t
Andreas Wundsam53256162013-05-02 14:05:53 -0700186of_%(name)s_to_object_id(int %(name)s, of_version_t version)
Rich Lanea06d0c32013-03-25 08:52:03 -0700187{
188 if (!OF_VERSION_OKAY(version)) {
189 return OF_OBJECT_INVALID;
190 }
191 if (%(name)s < 0 || %(name)s >= OF_%(u_name)s_ITEM_COUNT) {
192 return OF_OBJECT_INVALID;
193 }
194
195 return of_%(name)s_type_to_id[version][%(name)s];
196}
197"""
198 map_with_experimenter_template = """
199/**
200 * %(name)s wire type to object ID array.
201 * Treat as private; use function accessor below
202 */
203
Rich Laneb157b0f2013-03-27 13:55:28 -0700204extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];
Rich Lanea06d0c32013-03-25 08:52:03 -0700205
206#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n
207
208/**
209 * Map an %(name)s wire value to an OF object
210 * @param %(name)s The %(name)s type wire value
211 * @param version The version associated with the check
212 * @return The %(name)s OF object type
213 * @return OF_OBJECT_INVALID if type does not map to an object
Andreas Wundsam53256162013-05-02 14:05:53 -0700214 *
Rich Lanea06d0c32013-03-25 08:52:03 -0700215 */
Rich Lanec0e20ff2013-12-15 23:40:31 -0800216of_object_id_t
Andreas Wundsam53256162013-05-02 14:05:53 -0700217of_%(name)s_to_object_id(int %(name)s, of_version_t version)
Rich Lanea06d0c32013-03-25 08:52:03 -0700218{
219 if (!OF_VERSION_OKAY(version)) {
220 return OF_OBJECT_INVALID;
221 }
222 if (%(name)s == OF_EXPERIMENTER_TYPE) {
223 return OF_%(u_name)s_EXPERIMENTER;
224 }
225 if (%(name)s < 0 || %(name)s >= OF_%(u_name)s_ITEM_COUNT) {
226 return OF_OBJECT_INVALID;
227 }
228
229 return of_%(name)s_type_to_id[version][%(name)s];
230}
231"""
232
233 stats_template = """
234/**
235 * %(name)s wire type to object ID array.
236 * Treat as private; use function accessor below
237 */
238
Rich Laneb157b0f2013-03-27 13:55:28 -0700239extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];
Rich Lanea06d0c32013-03-25 08:52:03 -0700240
241#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n
242
243/**
244 * Map an %(name)s wire value to an OF object
245 * @param %(name)s The %(name)s type wire value
246 * @param version The version associated with the check
247 * @return The %(name)s OF object type
248 * @return OF_OBJECT_INVALID if type does not map to an object
Andreas Wundsam53256162013-05-02 14:05:53 -0700249 *
Rich Lanea06d0c32013-03-25 08:52:03 -0700250 */
Rich Lanec0e20ff2013-12-15 23:40:31 -0800251of_object_id_t
Andreas Wundsam53256162013-05-02 14:05:53 -0700252of_%(name)s_to_object_id(int %(name)s, of_version_t version)
Rich Lanea06d0c32013-03-25 08:52:03 -0700253{
254 if (!OF_VERSION_OKAY(version)) {
255 return OF_OBJECT_INVALID;
256 }
257 if (%(name)s == OF_EXPERIMENTER_TYPE) {
258 return OF_EXPERIMENTER_%(u_name)s;
259 }
260 if (%(name)s < 0 || %(name)s >= OF_%(u_name)s_ITEM_COUNT) {
261 return OF_OBJECT_INVALID;
262 }
263
264 return of_%(name)s_type_to_id[version][%(name)s];
265}
266"""
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700267
268 error_msg_template = """
269/**
270 * %(name)s wire type to object ID array.
271 * Treat as private; use function accessor below
272 */
273
274extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];
275
276#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n
277
278/**
279 * Map an %(name)s wire value to an OF object
280 * @param %(name)s The %(name)s type wire value
281 * @param version The version associated with the check
282 * @return The %(name)s OF object type
283 * @return OF_OBJECT_INVALID if type does not map to an object
284 *
285 */
Rich Lanec0e20ff2013-12-15 23:40:31 -0800286of_object_id_t
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700287of_error_msg_to_object_id(uint16_t %(name)s, of_version_t version)
288{
289 if (!OF_VERSION_OKAY(version)) {
290 return OF_OBJECT_INVALID;
291 }
292 if (%(name)s == OF_EXPERIMENTER_TYPE) {
293 return OF_EXPERIMENTER_ERROR_MSG;
294 }
295 if (%(name)s < 0 || %(name)s >= OF_%(u_name)s_ITEM_COUNT) {
296 return OF_OBJECT_INVALID;
297 }
298
299 return of_%(name)s_type_to_id[version][%(name)s];
300}
301"""
302
Rich Lanea06d0c32013-03-25 08:52:03 -0700303 # Experimenter mapping functions
304 # Currently we support very few candidates, so we just do a
305 # list of if/elses
306 experimenter_function = """
307/**
308 * @brief Map a message known to be an exp msg to the proper object
309 *
310 * Assume that the message is a vendor/experimenter message. Determine
311 * the specific object type for the message.
312 * @param msg An OF message object (uint8_t *)
313 * @param length The number of bytes in the message (for error checking)
314 * @param version Version of message
315 * @returns object ID of specific type if recognized or OF_EXPERIMENTER if not
316 *
317 * @todo put OF_EXPERIMENTER_<name> in loci_base.h
318 */
319
Rich Lanec0e20ff2013-12-15 23:40:31 -0800320of_object_id_t
Rich Lanea06d0c32013-03-25 08:52:03 -0700321of_message_experimenter_to_object_id(of_message_t msg, of_version_t version) {
322 uint32_t experimenter_id;
323 uint32_t subtype;
324
325 /* Extract experimenter and subtype value; look for match from type maps */
326 experimenter_id = of_message_experimenter_id_get(msg);
327 subtype = of_message_experimenter_subtype_get(msg);
328
329 /* Do a simple if/else search for the ver, experimenter and subtype */
330"""
331 first = True
332 for version, experimenter_lists in type_maps.extension_message_subtype.items():
333 for exp, subtypes in experimenter_lists.items():
334 experimenter_function += """
Andreas Wundsam53256162013-05-02 14:05:53 -0700335 if ((experimenter_id == OF_EXPERIMENTER_ID_%(exp_name)s) &&
Rich Lanea06d0c32013-03-25 08:52:03 -0700336 (version == %(ver_name)s)) {
337""" % dict(exp_name=exp.upper(), ver_name=of_g.wire_ver_map[version])
338 for ext_msg, subtype in subtypes.items():
339 experimenter_function += """
340 if (subtype == %(subtype)s) {
341 return %(ext_msg)s;
342 }
343""" % dict(subtype=subtype, ext_msg=ext_msg.upper())
344 experimenter_function += """
345 }
346"""
347 experimenter_function += """
348 return OF_EXPERIMENTER;
349}
350"""
351
352 # Message need different handling
353 msg_template = """
354/**
355 * %(name)s wire type to object ID array.
356 * Treat as private; use function accessor below
357 */
358
Rich Laneb157b0f2013-03-27 13:55:28 -0700359extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];
Rich Lanea06d0c32013-03-25 08:52:03 -0700360
361#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n
362
363/**
364 * Extract the type info from the message and determine its object type
365 * @param msg An OF message object (uint8_t *)
366 * @param length The number of bytes in the message (for error checking)
367 * @returns object ID or OF_OBJECT_INVALID if parse error
368 */
369
Rich Lanec0e20ff2013-12-15 23:40:31 -0800370of_object_id_t
Rich Lanea06d0c32013-03-25 08:52:03 -0700371of_message_to_object_id(of_message_t msg, int length) {
372 uint8_t type;
373 of_version_t ver;
374 of_object_id_t obj_id;
375 uint16_t stats_type;
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700376 uint16_t err_type;
Rich Lanea06d0c32013-03-25 08:52:03 -0700377 uint8_t flow_mod_cmd;
Rich Lane353a79f2013-11-13 10:39:56 -0800378 uint32_t experimenter, subtype;
Rich Lanee3113672013-12-06 17:09:57 -0800379 uint16_t group_mod_cmd;
Rich Lanea06d0c32013-03-25 08:52:03 -0700380
381 if (length < OF_MESSAGE_MIN_LENGTH) {
382 return OF_OBJECT_INVALID;
383 }
384 type = of_message_type_get(msg);
385 ver = of_message_version_get(msg);
386 if (!OF_VERSION_OKAY(ver)) {
387 return OF_OBJECT_INVALID;
388 }
389
390 if (type >= OF_MESSAGE_ITEM_COUNT) {
391 return OF_OBJECT_INVALID;
392 }
393
394 obj_id = of_message_type_to_id[ver][type];
395
396 /* Remap to specific message if known */
397 if (obj_id == OF_EXPERIMENTER) {
398 if (length < OF_MESSAGE_EXPERIMENTER_MIN_LENGTH) {
399 return OF_OBJECT_INVALID;
400 }
401 return of_message_experimenter_to_object_id(msg, ver);
402 }
403
404 /* Remap to add/delete/strict version */
405 if (obj_id == OF_FLOW_MOD) {
406 if (length < OF_MESSAGE_MIN_FLOW_MOD_LENGTH(ver)) {
407 return OF_OBJECT_INVALID;
408 }
409 flow_mod_cmd = of_message_flow_mod_command_get(msg, ver);
410 obj_id = of_flow_mod_to_object_id(flow_mod_cmd, ver);
411 }
412
413 if ((obj_id == OF_STATS_REQUEST) || (obj_id == OF_STATS_REPLY)) {
414 if (length < OF_MESSAGE_MIN_STATS_LENGTH) {
415 return OF_OBJECT_INVALID;
416 }
417 stats_type = of_message_stats_type_get(msg);
Rich Lane353a79f2013-11-13 10:39:56 -0800418 if (stats_type == OF_STATS_TYPE_EXPERIMENTER) {
419 if (length < OF_MESSAGE_STATS_EXPERIMENTER_MIN_LENGTH) {
420 return OF_OBJECT_INVALID;
421 }
422 experimenter = of_message_stats_experimenter_id_get(msg);
423 subtype = of_message_stats_experimenter_subtype_get(msg);
424 if (obj_id == OF_STATS_REQUEST) {
425 obj_id = of_experimenter_stats_request_to_object_id(experimenter, subtype, ver);
426 } else {
427 obj_id = of_experimenter_stats_reply_to_object_id(experimenter, subtype, ver);
428 }
Rich Lanea06d0c32013-03-25 08:52:03 -0700429 } else {
Rich Lane353a79f2013-11-13 10:39:56 -0800430 if (obj_id == OF_STATS_REQUEST) {
431 obj_id = of_stats_request_to_object_id(stats_type, ver);
432 } else {
433 obj_id = of_stats_reply_to_object_id(stats_type, ver);
434 }
Rich Lanea06d0c32013-03-25 08:52:03 -0700435 }
436 }
437
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700438 if (obj_id == OF_ERROR_MSG) {
439 if (length < OF_MESSAGE_MIN_ERROR_LENGTH) {
440 return OF_OBJECT_INVALID;
441 }
442 err_type = of_message_error_type_get(msg);
443 obj_id = of_error_msg_to_object_id(err_type, ver);
444 }
445
Rich Lanee3113672013-12-06 17:09:57 -0800446 if (obj_id == OF_GROUP_MOD) {
447 if (length < OF_MESSAGE_MIN_GROUP_MOD_LENGTH) {
448 return OF_OBJECT_INVALID;
449 }
450 group_mod_cmd = of_message_group_mod_command_get(msg);
451 obj_id = of_group_mod_to_object_id(group_mod_cmd, ver);
452 }
453
Rich Lanea06d0c32013-03-25 08:52:03 -0700454 return obj_id;
455}
456"""
457
Rich Laned8d29c92013-09-24 13:46:42 -0700458 oxm_template = """
459/**
460 * oxm wire type to object ID array.
461 * Treat as private; use function accessor below
462 */
463
464extern const of_object_id_t *const of_oxm_type_to_id[OF_VERSION_ARRAY_MAX];
465
466#define OF_OXM_ITEM_COUNT %(ar_len)d\n
467
468/**
469 * Map an oxm wire value to an OF object
470 * @param oxm The oxm type wire value
471 * @param version The version associated with the check
472 * @return The oxm OF object type
473 * @return OF_OBJECT_INVALID if type does not map to an object
474 *
475 */
Rich Lanec0e20ff2013-12-15 23:40:31 -0800476of_object_id_t
Rich Laned8d29c92013-09-24 13:46:42 -0700477of_oxm_to_object_id(uint32_t type_len, of_version_t version)
478{
479 if (!OF_VERSION_OKAY(version)) {
480 return OF_OBJECT_INVALID;
481 }
482
483 uint16_t class = (type_len >> 16) & 0xffff;
484 uint8_t masked_type = (type_len >> 8) & 0xff;
485
486 if (class == 0x8000) {
487 if (masked_type < 0 || masked_type >= OF_OXM_ITEM_COUNT) {
488 return OF_OBJECT_INVALID;
489 }
490
491 return of_oxm_type_to_id[version][masked_type];
492 } else if (class == 0x0003) {
493 switch (masked_type) {
494 case 0x00: return OF_OXM_BSN_IN_PORTS_128;
495 case 0x01: return OF_OXM_BSN_IN_PORTS_128_MASKED;
Rich Lane61718362013-10-24 16:59:42 -0700496 case 0x02: return OF_OXM_BSN_LAG_ID;
497 case 0x03: return OF_OXM_BSN_LAG_ID_MASKED;
Rich Laneeb21c4f2013-10-28 17:34:41 -0700498 case 0x04: return OF_OXM_BSN_VRF;
499 case 0x05: return OF_OXM_BSN_VRF_MASKED;
500 case 0x06: return OF_OXM_BSN_GLOBAL_VRF_ALLOWED;
501 case 0x07: return OF_OXM_BSN_GLOBAL_VRF_ALLOWED_MASKED;
502 case 0x08: return OF_OXM_BSN_L3_INTERFACE_CLASS_ID;
503 case 0x09: return OF_OXM_BSN_L3_INTERFACE_CLASS_ID_MASKED;
504 case 0x0a: return OF_OXM_BSN_L3_SRC_CLASS_ID;
505 case 0x0b: return OF_OXM_BSN_L3_SRC_CLASS_ID_MASKED;
506 case 0x0c: return OF_OXM_BSN_L3_DST_CLASS_ID;
507 case 0x0d: return OF_OXM_BSN_L3_DST_CLASS_ID_MASKED;
Rich Laned8d29c92013-09-24 13:46:42 -0700508 default: return OF_OBJECT_INVALID;
509 }
510 } else {
511 return OF_OBJECT_INVALID;
512 }
513}
514"""
515
Rich Lanea06d0c32013-03-25 08:52:03 -0700516 # Action types array gen
517 ar_len = type_maps.type_array_len(type_maps.action_types, max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700518 out.write(map_with_experimenter_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700519 dict(name="action", u_name="ACTION", ar_len=ar_len))
520
521 # Action ID types array gen
522 ar_len = type_maps.type_array_len(type_maps.action_id_types, max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700523 out.write(map_with_experimenter_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700524 dict(name="action_id", u_name="ACTION_ID", ar_len=ar_len))
525
526 # Instruction types array gen
527 ar_len = type_maps.type_array_len(type_maps.instruction_types,
528 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700529 out.write(map_with_experimenter_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700530 dict(name="instruction", u_name="INSTRUCTION", ar_len=ar_len))
531
532 # Queue prop types array gen
533 ar_len = type_maps.type_array_len(type_maps.queue_prop_types,
534 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700535 out.write(map_with_experimenter_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700536 dict(name="queue_prop", u_name="QUEUE_PROP", ar_len=ar_len))
537
538 # Table feature prop types array gen
539 ar_len = type_maps.type_array_len(type_maps.table_feature_prop_types,
540 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700541 out.write(map_with_experimenter_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700542 dict(name="table_feature_prop", u_name="TABLE_FEATURE_PROP",
543 ar_len=ar_len))
544
545 # Meter band types array gen
546 ar_len = type_maps.type_array_len(type_maps.meter_band_types,
547 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700548 out.write(map_with_experimenter_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700549 dict(name="meter_band", u_name="METER_BAND", ar_len=ar_len))
550
551 # Hello elem types array gen
552 ar_len = type_maps.type_array_len(type_maps.hello_elem_types,
553 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700554 out.write(map_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700555 dict(name="hello_elem", u_name="HELLO_ELEM", ar_len=ar_len))
556
557 # Stats types array gen
558 ar_len = type_maps.type_array_len(type_maps.stats_types,
559 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700560 out.write(stats_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700561 dict(name="stats_reply", u_name="STATS_REPLY", ar_len=ar_len))
Andreas Wundsam53256162013-05-02 14:05:53 -0700562 out.write(stats_template %
563 dict(name="stats_request", u_name="STATS_REQUEST",
Rich Lanea06d0c32013-03-25 08:52:03 -0700564 ar_len=ar_len))
565
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700566 ar_len = type_maps.type_array_len(type_maps.error_types,
567 max_type_value)
568 out.write(error_msg_template %
569 dict(name="error_msg", u_name="ERROR_MSG", ar_len=ar_len))
570# out.write(error_msg_function)
571
Rich Lanea06d0c32013-03-25 08:52:03 -0700572 ar_len = type_maps.type_array_len(type_maps.flow_mod_types, max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700573 out.write(map_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700574 dict(name="flow_mod", u_name="FLOW_MOD", ar_len=ar_len))
575
Rich Lanee3113672013-12-06 17:09:57 -0800576 ar_len = type_maps.type_array_len(type_maps.group_mod_types,
577 max_type_value)
578 out.write(map_template %
579 dict(name="group_mod", u_name="GROUP_MOD", ar_len=ar_len))
580
Rich Laned8d29c92013-09-24 13:46:42 -0700581 # OXM
Rich Lanea06d0c32013-03-25 08:52:03 -0700582 ar_len = type_maps.type_array_len(type_maps.oxm_types, max_type_value)
583 out.write("""
584/* NOTE: We could optimize the OXM and only generate OF 1.2 versions. */
585""")
Rich Laned8d29c92013-09-24 13:46:42 -0700586 out.write(oxm_template % dict(ar_len=ar_len))
Rich Lanea06d0c32013-03-25 08:52:03 -0700587
Rich Laned8d29c92013-09-24 13:46:42 -0700588 # Messages
Rich Lanea06d0c32013-03-25 08:52:03 -0700589 out.write(experimenter_function)
590 # Must follow stats reply/request
591 ar_len = type_maps.type_array_len(type_maps.message_types, max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700592 out.write(msg_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700593 dict(name="message", u_name="MESSAGE", ar_len=ar_len))
594
Rich Lane713d9282013-12-30 15:21:35 -0800595 # BSN TLV elem types array gen
596 ar_len = type_maps.type_array_len(type_maps.bsn_tlv_types,
597 max_type_value)
598 out.write(map_template %
599 dict(name="bsn_tlv", u_name="BSN_TLV", ar_len=ar_len))
600
Rich Lanea06d0c32013-03-25 08:52:03 -0700601def gen_type_data_header(out):
602
603 out.write("""
604/****************************************************************
605 *
606 * The following declarations are for type and length calculations.
607 * Implementations may be found in of_type_maps.c
608 *
609 ****************************************************************/
610/*
611 * Special case length functions for objects with
612 */
613""")
614 for ((cls, name), prev) in of_g.special_offsets.items():
615 s_cls = cls[3:] # take off of_
616 out.write("""
617/**
618 * Special length calculation for %(cls)s->%(name)s.
Andreas Wundsam53256162013-05-02 14:05:53 -0700619 * @param obj An object of type %(cls)s to check for
Rich Lanea06d0c32013-03-25 08:52:03 -0700620 * length of %(name)s
621 * @param bytes[out] Where to store the calculated length
622 *
623 * Preceding data member is %(prev)s.
624 */
625extern int of_length_%(s_cls)s_%(name)s_get(
626 %(cls)s_t *obj, int *bytes);
627
628/**
629 * Special offset calculation for %(cls)s->%(name)s.
Andreas Wundsam53256162013-05-02 14:05:53 -0700630 * @param obj An object of type %(cls)s to check for
Rich Lanea06d0c32013-03-25 08:52:03 -0700631 * length of %(name)s
632 * @param offset[out] Where to store the calculated length
633 *
634 * Preceding data member is %(prev)s.
635 */
636extern int of_offset_%(s_cls)s_%(name)s_get(
637 %(cls)s_t *obj, int *offset);
638""" % dict(cls=cls, s_cls=s_cls, name=name, prev=prev))
639
640# NOT NEEDED YET
641# # For non-message, variable length objects, give a fun that
642# # calculates the length
643# for cls in of_g.standard_class_order:
644# s_cls = cls[3:] # take off of_
645# if !type_is_var_len(cls, version):
646# continue
647# out.write("""
648# /**
649# * Special length calculation for variable length object %(cls)s
650# * @param obj An object of type %(cls)s whose length is being calculated
651# * @param bytes[out] Where to store the calculated length
652# *
653# * The assumption is that the length member of the object is not
654# * valid and the length needs to be calculated from other information
655# * such as the parent.
656# */
657# extern int of_length_%(s_cls)s_get(
658# %(cls)s_t *obj, int *bytes);
Andreas Wundsam53256162013-05-02 14:05:53 -0700659# """ % dict(cls=cls, s_cls=s_cls))
Rich Lanea06d0c32013-03-25 08:52:03 -0700660
661 out.write("""
662/****************************************************************
663 * Wire type/length functions.
664 ****************************************************************/
665
666extern void of_object_message_wire_length_get(of_object_t *obj, int *bytes);
667extern void of_object_message_wire_length_set(of_object_t *obj, int bytes);
668
669extern void of_oxm_wire_length_get(of_object_t *obj, int *bytes);
Rich Lanea06d0c32013-03-25 08:52:03 -0700670extern void of_oxm_wire_object_id_get(of_object_t *obj, of_object_id_t *id);
Rich Lanea06d0c32013-03-25 08:52:03 -0700671
672extern void of_tlv16_wire_length_get(of_object_t *obj, int *bytes);
673extern void of_tlv16_wire_length_set(of_object_t *obj, int bytes);
674
Rich Lanea06d0c32013-03-25 08:52:03 -0700675/* Wire length is uint16 at front of structure */
676extern void of_u16_len_wire_length_get(of_object_t *obj, int *bytes);
677extern void of_u16_len_wire_length_set(of_object_t *obj, int bytes);
678
679extern void of_action_wire_object_id_get(of_object_t *obj, of_object_id_t *id);
680extern void of_action_id_wire_object_id_get(of_object_t *obj, of_object_id_t *id);
Andreas Wundsam53256162013-05-02 14:05:53 -0700681extern void of_instruction_wire_object_id_get(of_object_t *obj,
Rich Lanea06d0c32013-03-25 08:52:03 -0700682 of_object_id_t *id);
Andreas Wundsam53256162013-05-02 14:05:53 -0700683extern void of_queue_prop_wire_object_id_get(of_object_t *obj,
Rich Lanea06d0c32013-03-25 08:52:03 -0700684 of_object_id_t *id);
Andreas Wundsam53256162013-05-02 14:05:53 -0700685extern void of_table_feature_prop_wire_object_id_get(of_object_t *obj,
Rich Lanea06d0c32013-03-25 08:52:03 -0700686 of_object_id_t *id);
Andreas Wundsam53256162013-05-02 14:05:53 -0700687extern void of_meter_band_wire_object_id_get(of_object_t *obj,
Rich Lanea06d0c32013-03-25 08:52:03 -0700688 of_object_id_t *id);
Andreas Wundsam53256162013-05-02 14:05:53 -0700689extern void of_hello_elem_wire_object_id_get(of_object_t *obj,
Rich Lanea06d0c32013-03-25 08:52:03 -0700690 of_object_id_t *id);
Rich Lane713d9282013-12-30 15:21:35 -0800691extern void of_bsn_tlv_wire_object_id_get(of_object_t *obj,
692 of_object_id_t *id);
Rich Lanea06d0c32013-03-25 08:52:03 -0700693
Rich Lane47085722013-07-12 16:27:04 -0700694#define OF_OXM_LENGTH_GET(hdr) (((hdr) & 0xff) + 4)
Rich Lanea06d0c32013-03-25 08:52:03 -0700695#define OF_OXM_LENGTH_SET(hdr, val) \\
Rich Lane47085722013-07-12 16:27:04 -0700696 (hdr) = ((hdr) & 0xffffff00) + (((val) - 4) & 0xff)
Rich Lanea06d0c32013-03-25 08:52:03 -0700697
698extern void of_packet_queue_wire_length_get(of_object_t *obj, int *bytes);
699extern void of_packet_queue_wire_length_set(of_object_t *obj, int bytes);
700
701extern void of_list_meter_band_stats_wire_length_get(of_object_t *obj,
702 int *bytes);
703extern void of_meter_stats_wire_length_get(of_object_t *obj, int *bytes);
704extern void of_meter_stats_wire_length_set(of_object_t *obj, int bytes);
705extern int of_extension_object_wire_push(of_object_t *obj);
706
707""")
708
709
710def gen_length_array(out):
711 """
712 Generate an array giving the lengths of all objects/versions
713 @param out The file handle to which to write
714 """
715 out.write("""
716/**
717 * An array with the number of bytes in the fixed length part
718 * of each OF object
719 */
720""")
721
722 for version in of_g.of_version_range:
723 out.write("""
Rich Laneb157b0f2013-03-27 13:55:28 -0700724static const int\nof_object_fixed_len_v%d[OF_OBJECT_COUNT] = {
Rich Lanea06d0c32013-03-25 08:52:03 -0700725 -1, /* of_object is not instantiable */
726""" % version)
727 for i, cls in enumerate(of_g.all_class_order):
728 comma = ","
729 if i == len(of_g.all_class_order) - 1:
730 comma = ""
731 val = "-1" + comma
732 if (cls, version) in of_g.base_length:
733 val = str(of_g.base_length[(cls, version)]) + comma
734 out.write(" %-5s /* %d: %s */\n" % (val, i + 1, cls))
735 out.write("};\n")
736
737 out.write("""
738/**
739 * Unified map of fixed length part of each object
740 */
Rich Laneb157b0f2013-03-27 13:55:28 -0700741const int *const of_object_fixed_len[OF_VERSION_ARRAY_MAX] = {
Rich Lanea06d0c32013-03-25 08:52:03 -0700742 NULL,
743""")
744 for version in of_g.of_version_range:
745 out.write(" of_object_fixed_len_v%d,\n" % version)
746 out.write("""
747};
748""")
749
Andreas Wundsam53256162013-05-02 14:05:53 -0700750
Rich Lanef70be942013-07-18 13:33:14 -0700751def gen_extra_length_array(out):
752 """
753 Generate an array giving the extra lengths of all objects/versions
754 @param out The file handle to which to write
755 """
756 out.write("""
757/**
758 * An array with the number of bytes in the extra length part
759 * of each OF object
760 */
761""")
762
763 for version in of_g.of_version_range:
764 out.write("""
765static const int\nof_object_extra_len_v%d[OF_OBJECT_COUNT] = {
766 -1, /* of_object is not instantiable */
767""" % version)
768 for i, cls in enumerate(of_g.all_class_order):
769 comma = ","
770 if i == len(of_g.all_class_order) - 1:
771 comma = ""
772 val = "-1" + comma
773 if (cls, version) in of_g.base_length:
774 val = str(of_g.extra_length.get((cls, version), 0)) + comma
775 out.write(" %-5s /* %d: %s */\n" % (val, i + 1, cls))
776 out.write("};\n")
777
778 out.write("""
779/**
780 * Unified map of extra length part of each object
781 */
782const int *const of_object_extra_len[OF_VERSION_ARRAY_MAX] = {
783 NULL,
784""")
785 for version in of_g.of_version_range:
786 out.write(" of_object_extra_len_v%d,\n" % version)
787 out.write("""
788};
789""")