blob: 5f4ac6c93d4fa823457c6d27d3b82fc1ac3a3c5a [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)
Jonathan Stout83cedcc2014-03-03 16:38:00 -0500121 gen_type_to_object_id(out, "instruction_id_type_to_id", "OF_INSTRUCTION",
122 "OF_INSTRUCTION_ID_%s", type_maps.instruction_id_types,
123 max_type_value)
Rich Lanea06d0c32013-03-25 08:52:03 -0700124 gen_type_to_object_id(out, "queue_prop_type_to_id", "OF_QUEUE_PROP",
125 "OF_QUEUE_PROP_%s", type_maps.queue_prop_types,
126 max_type_value)
127 gen_type_to_object_id(out, "table_feature_prop_type_to_id",
128 "OF_TABLE_FEATURE_PROP",
129 "OF_TABLE_FEATURE_PROP_%s",
130 type_maps.table_feature_prop_types,
131 max_type_value)
132 gen_type_to_object_id(out, "meter_band_type_to_id", "OF_METER_BAND",
133 "OF_METER_BAND_%s", type_maps.meter_band_types,
134 max_type_value)
135 gen_type_to_object_id(out, "hello_elem_type_to_id", "OF_HELLO_ELEM",
136 "OF_HELLO_ELEM_%s", type_maps.hello_elem_types,
137 max_type_value)
Rich Lanee3113672013-12-06 17:09:57 -0800138 gen_type_to_object_id(out, "group_mod_type_to_id", "OF_GROUP_MOD",
139 "OF_GROUP_%s", type_maps.group_mod_types,
140 max_type_value)
Rich Lanea06d0c32013-03-25 08:52:03 -0700141
142 # FIXME: Multipart re-organization
143 gen_type_to_object_id(out, "stats_request_type_to_id", "OF_STATS_REQUEST",
144 "OF_%s_STATS_REQUEST", type_maps.stats_types,
145 max_type_value)
146 gen_type_to_object_id(out, "stats_reply_type_to_id", "OF_STATS_REPLY",
147 "OF_%s_STATS_REPLY", type_maps.stats_types,
148 max_type_value)
149 gen_type_to_object_id(out, "flow_mod_type_to_id", "OF_FLOW_MOD",
150 "OF_FLOW_%s", type_maps.flow_mod_types,
151 max_type_value)
152 gen_type_to_object_id(out, "oxm_type_to_id", "OF_OXM",
153 "OF_OXM_%s", type_maps.oxm_types, max_type_value)
154 gen_type_to_object_id(out, "message_type_to_id", "OF_MESSAGE",
155 "OF_%s", type_maps.message_types, max_type_value)
156
Rich Lane713d9282013-12-30 15:21:35 -0800157 gen_type_to_object_id(out, "bsn_tlv_type_to_id", "OF_BSN_TLV",
158 "OF_BSN_TLV_%s", type_maps.bsn_tlv_types,
159 max_type_value)
160
Rich Lanea06d0c32013-03-25 08:52:03 -0700161def gen_type_to_obj_map_functions(out):
162 """
Rich Lanec0e20ff2013-12-15 23:40:31 -0800163 Generate the templated type map functions
Rich Lanea06d0c32013-03-25 08:52:03 -0700164 @param out The file handle to write to
165 """
166
167 ################################################################
168 # Generate all type-to-object-ID maps in a common way
169 ################################################################
170 map_template = """
171/**
172 * %(name)s wire type to object ID array.
173 * Treat as private; use function accessor below
174 */
175
Rich Laneb157b0f2013-03-27 13:55:28 -0700176extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];
Rich Lanea06d0c32013-03-25 08:52:03 -0700177
178#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n
179
180/**
181 * Map an %(name)s wire value to an OF object
182 * @param %(name)s The %(name)s type wire value
183 * @param version The version associated with the check
184 * @return The %(name)s OF object type
185 * @return OF_OBJECT_INVALID if type does not map to an object
Andreas Wundsam53256162013-05-02 14:05:53 -0700186 *
Rich Lanea06d0c32013-03-25 08:52:03 -0700187 */
Rich Lanec0e20ff2013-12-15 23:40:31 -0800188of_object_id_t
Andreas Wundsam53256162013-05-02 14:05:53 -0700189of_%(name)s_to_object_id(int %(name)s, of_version_t version)
Rich Lanea06d0c32013-03-25 08:52:03 -0700190{
191 if (!OF_VERSION_OKAY(version)) {
192 return OF_OBJECT_INVALID;
193 }
194 if (%(name)s < 0 || %(name)s >= OF_%(u_name)s_ITEM_COUNT) {
195 return OF_OBJECT_INVALID;
196 }
197
198 return of_%(name)s_type_to_id[version][%(name)s];
199}
200"""
201 map_with_experimenter_template = """
202/**
203 * %(name)s wire type to object ID array.
204 * Treat as private; use function accessor below
205 */
206
Rich Laneb157b0f2013-03-27 13:55:28 -0700207extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];
Rich Lanea06d0c32013-03-25 08:52:03 -0700208
209#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n
210
211/**
212 * Map an %(name)s wire value to an OF object
213 * @param %(name)s The %(name)s type wire value
214 * @param version The version associated with the check
215 * @return The %(name)s OF object type
216 * @return OF_OBJECT_INVALID if type does not map to an object
Andreas Wundsam53256162013-05-02 14:05:53 -0700217 *
Rich Lanea06d0c32013-03-25 08:52:03 -0700218 */
Rich Lanec0e20ff2013-12-15 23:40:31 -0800219of_object_id_t
Andreas Wundsam53256162013-05-02 14:05:53 -0700220of_%(name)s_to_object_id(int %(name)s, of_version_t version)
Rich Lanea06d0c32013-03-25 08:52:03 -0700221{
222 if (!OF_VERSION_OKAY(version)) {
223 return OF_OBJECT_INVALID;
224 }
225 if (%(name)s == OF_EXPERIMENTER_TYPE) {
226 return OF_%(u_name)s_EXPERIMENTER;
227 }
228 if (%(name)s < 0 || %(name)s >= OF_%(u_name)s_ITEM_COUNT) {
229 return OF_OBJECT_INVALID;
230 }
231
232 return of_%(name)s_type_to_id[version][%(name)s];
233}
234"""
Jonathan Stouta226fd72014-02-13 16:36:07 -0500235 table_features_prop_template = """
236/**
237 * %(name)s wire type to object ID array.
238 * Treat as private; use function accessor below
239 */
Rich Lanea06d0c32013-03-25 08:52:03 -0700240
Jonathan Stouta226fd72014-02-13 16:36:07 -0500241extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];
242
243#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n
244
245/**
246 * Map an %(name)s wire value to an OF object
247 * @param %(name)s The %(name)s type wire value
248 * @param version The version associated with the check
249 * @return The %(name)s OF object type
250 * @return OF_OBJECT_INVALID if type does not map to an object
251 *
252 */
253of_object_id_t
254of_%(name)s_to_object_id(int %(name)s, of_version_t version)
255{
256 if (!OF_VERSION_OKAY(version)) {
257 return OF_OBJECT_INVALID;
258 }
Jonathan Stouted300e02014-02-14 14:04:05 -0500259 if (%(name)s == 0xfffe) {
Jonathan Stouta226fd72014-02-13 16:36:07 -0500260 return OF_%(u_name)s_EXPERIMENTER;
261 }
Jonathan Stouted300e02014-02-14 14:04:05 -0500262 if (%(name)s == 0xffff) {
Jonathan Stout7a65c002014-02-13 17:27:28 -0500263 return OF_%(u_name)s_EXPERIMENTER_MISS;
264 }
Jonathan Stouta226fd72014-02-13 16:36:07 -0500265 if (%(name)s < 0 || %(name)s >= OF_%(u_name)s_ITEM_COUNT) {
266 return OF_OBJECT_INVALID;
267 }
268
269 return of_%(name)s_type_to_id[version][%(name)s];
270}
271"""
Rich Lanea06d0c32013-03-25 08:52:03 -0700272 stats_template = """
273/**
274 * %(name)s wire type to object ID array.
275 * Treat as private; use function accessor below
276 */
277
Rich Laneb157b0f2013-03-27 13:55:28 -0700278extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];
Rich Lanea06d0c32013-03-25 08:52:03 -0700279
280#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n
281
282/**
283 * Map an %(name)s wire value to an OF object
284 * @param %(name)s The %(name)s type wire value
285 * @param version The version associated with the check
286 * @return The %(name)s OF object type
287 * @return OF_OBJECT_INVALID if type does not map to an object
Andreas Wundsam53256162013-05-02 14:05:53 -0700288 *
Rich Lanea06d0c32013-03-25 08:52:03 -0700289 */
Rich Lanec0e20ff2013-12-15 23:40:31 -0800290of_object_id_t
Andreas Wundsam53256162013-05-02 14:05:53 -0700291of_%(name)s_to_object_id(int %(name)s, of_version_t version)
Rich Lanea06d0c32013-03-25 08:52:03 -0700292{
293 if (!OF_VERSION_OKAY(version)) {
294 return OF_OBJECT_INVALID;
295 }
296 if (%(name)s == OF_EXPERIMENTER_TYPE) {
297 return OF_EXPERIMENTER_%(u_name)s;
298 }
299 if (%(name)s < 0 || %(name)s >= OF_%(u_name)s_ITEM_COUNT) {
300 return OF_OBJECT_INVALID;
301 }
302
303 return of_%(name)s_type_to_id[version][%(name)s];
304}
305"""
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700306
307 error_msg_template = """
308/**
309 * %(name)s wire type to object ID array.
310 * Treat as private; use function accessor below
311 */
312
313extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];
314
315#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n
316
317/**
318 * Map an %(name)s wire value to an OF object
319 * @param %(name)s The %(name)s type wire value
320 * @param version The version associated with the check
321 * @return The %(name)s OF object type
322 * @return OF_OBJECT_INVALID if type does not map to an object
323 *
324 */
Rich Lanec0e20ff2013-12-15 23:40:31 -0800325of_object_id_t
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700326of_error_msg_to_object_id(uint16_t %(name)s, of_version_t version)
327{
328 if (!OF_VERSION_OKAY(version)) {
329 return OF_OBJECT_INVALID;
330 }
331 if (%(name)s == OF_EXPERIMENTER_TYPE) {
332 return OF_EXPERIMENTER_ERROR_MSG;
333 }
334 if (%(name)s < 0 || %(name)s >= OF_%(u_name)s_ITEM_COUNT) {
335 return OF_OBJECT_INVALID;
336 }
337
338 return of_%(name)s_type_to_id[version][%(name)s];
339}
340"""
341
Rich Lanea06d0c32013-03-25 08:52:03 -0700342 # Experimenter mapping functions
343 # Currently we support very few candidates, so we just do a
344 # list of if/elses
345 experimenter_function = """
346/**
347 * @brief Map a message known to be an exp msg to the proper object
348 *
349 * Assume that the message is a vendor/experimenter message. Determine
350 * the specific object type for the message.
351 * @param msg An OF message object (uint8_t *)
352 * @param length The number of bytes in the message (for error checking)
353 * @param version Version of message
354 * @returns object ID of specific type if recognized or OF_EXPERIMENTER if not
355 *
356 * @todo put OF_EXPERIMENTER_<name> in loci_base.h
357 */
358
Rich Lanec0e20ff2013-12-15 23:40:31 -0800359of_object_id_t
Rich Lanea06d0c32013-03-25 08:52:03 -0700360of_message_experimenter_to_object_id(of_message_t msg, of_version_t version) {
361 uint32_t experimenter_id;
362 uint32_t subtype;
363
364 /* Extract experimenter and subtype value; look for match from type maps */
365 experimenter_id = of_message_experimenter_id_get(msg);
366 subtype = of_message_experimenter_subtype_get(msg);
367
368 /* Do a simple if/else search for the ver, experimenter and subtype */
369"""
370 first = True
371 for version, experimenter_lists in type_maps.extension_message_subtype.items():
372 for exp, subtypes in experimenter_lists.items():
373 experimenter_function += """
Andreas Wundsam53256162013-05-02 14:05:53 -0700374 if ((experimenter_id == OF_EXPERIMENTER_ID_%(exp_name)s) &&
Rich Lanea06d0c32013-03-25 08:52:03 -0700375 (version == %(ver_name)s)) {
376""" % dict(exp_name=exp.upper(), ver_name=of_g.wire_ver_map[version])
377 for ext_msg, subtype in subtypes.items():
378 experimenter_function += """
379 if (subtype == %(subtype)s) {
380 return %(ext_msg)s;
381 }
382""" % dict(subtype=subtype, ext_msg=ext_msg.upper())
383 experimenter_function += """
384 }
385"""
386 experimenter_function += """
387 return OF_EXPERIMENTER;
388}
389"""
390
391 # Message need different handling
392 msg_template = """
393/**
394 * %(name)s wire type to object ID array.
395 * Treat as private; use function accessor below
396 */
397
Rich Laneb157b0f2013-03-27 13:55:28 -0700398extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];
Rich Lanea06d0c32013-03-25 08:52:03 -0700399
400#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n
401
402/**
403 * Extract the type info from the message and determine its object type
404 * @param msg An OF message object (uint8_t *)
405 * @param length The number of bytes in the message (for error checking)
406 * @returns object ID or OF_OBJECT_INVALID if parse error
407 */
408
Rich Lanec0e20ff2013-12-15 23:40:31 -0800409of_object_id_t
Rich Lanea06d0c32013-03-25 08:52:03 -0700410of_message_to_object_id(of_message_t msg, int length) {
411 uint8_t type;
412 of_version_t ver;
413 of_object_id_t obj_id;
414 uint16_t stats_type;
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700415 uint16_t err_type;
Rich Lanea06d0c32013-03-25 08:52:03 -0700416 uint8_t flow_mod_cmd;
Rich Lane353a79f2013-11-13 10:39:56 -0800417 uint32_t experimenter, subtype;
Rich Lanee3113672013-12-06 17:09:57 -0800418 uint16_t group_mod_cmd;
Rich Lanea06d0c32013-03-25 08:52:03 -0700419
420 if (length < OF_MESSAGE_MIN_LENGTH) {
421 return OF_OBJECT_INVALID;
422 }
423 type = of_message_type_get(msg);
424 ver = of_message_version_get(msg);
425 if (!OF_VERSION_OKAY(ver)) {
426 return OF_OBJECT_INVALID;
427 }
428
429 if (type >= OF_MESSAGE_ITEM_COUNT) {
430 return OF_OBJECT_INVALID;
431 }
432
433 obj_id = of_message_type_to_id[ver][type];
434
435 /* Remap to specific message if known */
436 if (obj_id == OF_EXPERIMENTER) {
437 if (length < OF_MESSAGE_EXPERIMENTER_MIN_LENGTH) {
438 return OF_OBJECT_INVALID;
439 }
440 return of_message_experimenter_to_object_id(msg, ver);
441 }
442
443 /* Remap to add/delete/strict version */
444 if (obj_id == OF_FLOW_MOD) {
445 if (length < OF_MESSAGE_MIN_FLOW_MOD_LENGTH(ver)) {
446 return OF_OBJECT_INVALID;
447 }
448 flow_mod_cmd = of_message_flow_mod_command_get(msg, ver);
449 obj_id = of_flow_mod_to_object_id(flow_mod_cmd, ver);
450 }
451
452 if ((obj_id == OF_STATS_REQUEST) || (obj_id == OF_STATS_REPLY)) {
453 if (length < OF_MESSAGE_MIN_STATS_LENGTH) {
454 return OF_OBJECT_INVALID;
455 }
456 stats_type = of_message_stats_type_get(msg);
Rich Lane353a79f2013-11-13 10:39:56 -0800457 if (stats_type == OF_STATS_TYPE_EXPERIMENTER) {
458 if (length < OF_MESSAGE_STATS_EXPERIMENTER_MIN_LENGTH) {
459 return OF_OBJECT_INVALID;
460 }
461 experimenter = of_message_stats_experimenter_id_get(msg);
462 subtype = of_message_stats_experimenter_subtype_get(msg);
463 if (obj_id == OF_STATS_REQUEST) {
464 obj_id = of_experimenter_stats_request_to_object_id(experimenter, subtype, ver);
465 } else {
466 obj_id = of_experimenter_stats_reply_to_object_id(experimenter, subtype, ver);
467 }
Rich Lanea06d0c32013-03-25 08:52:03 -0700468 } else {
Rich Lane353a79f2013-11-13 10:39:56 -0800469 if (obj_id == OF_STATS_REQUEST) {
470 obj_id = of_stats_request_to_object_id(stats_type, ver);
471 } else {
472 obj_id = of_stats_reply_to_object_id(stats_type, ver);
473 }
Rich Lanea06d0c32013-03-25 08:52:03 -0700474 }
475 }
476
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700477 if (obj_id == OF_ERROR_MSG) {
478 if (length < OF_MESSAGE_MIN_ERROR_LENGTH) {
479 return OF_OBJECT_INVALID;
480 }
481 err_type = of_message_error_type_get(msg);
482 obj_id = of_error_msg_to_object_id(err_type, ver);
483 }
484
Rich Lanee3113672013-12-06 17:09:57 -0800485 if (obj_id == OF_GROUP_MOD) {
486 if (length < OF_MESSAGE_MIN_GROUP_MOD_LENGTH) {
487 return OF_OBJECT_INVALID;
488 }
489 group_mod_cmd = of_message_group_mod_command_get(msg);
490 obj_id = of_group_mod_to_object_id(group_mod_cmd, ver);
491 }
492
Rich Lanea06d0c32013-03-25 08:52:03 -0700493 return obj_id;
494}
495"""
496
Rich Laned8d29c92013-09-24 13:46:42 -0700497 oxm_template = """
498/**
499 * oxm wire type to object ID array.
500 * Treat as private; use function accessor below
501 */
502
503extern const of_object_id_t *const of_oxm_type_to_id[OF_VERSION_ARRAY_MAX];
504
505#define OF_OXM_ITEM_COUNT %(ar_len)d\n
506
507/**
508 * Map an oxm wire value to an OF object
509 * @param oxm The oxm type wire value
510 * @param version The version associated with the check
511 * @return The oxm OF object type
512 * @return OF_OBJECT_INVALID if type does not map to an object
513 *
514 */
Rich Lanec0e20ff2013-12-15 23:40:31 -0800515of_object_id_t
Rich Laned8d29c92013-09-24 13:46:42 -0700516of_oxm_to_object_id(uint32_t type_len, of_version_t version)
517{
518 if (!OF_VERSION_OKAY(version)) {
519 return OF_OBJECT_INVALID;
520 }
521
522 uint16_t class = (type_len >> 16) & 0xffff;
523 uint8_t masked_type = (type_len >> 8) & 0xff;
524
525 if (class == 0x8000) {
526 if (masked_type < 0 || masked_type >= OF_OXM_ITEM_COUNT) {
527 return OF_OBJECT_INVALID;
528 }
529
530 return of_oxm_type_to_id[version][masked_type];
531 } else if (class == 0x0003) {
532 switch (masked_type) {
533 case 0x00: return OF_OXM_BSN_IN_PORTS_128;
534 case 0x01: return OF_OXM_BSN_IN_PORTS_128_MASKED;
Rich Lane61718362013-10-24 16:59:42 -0700535 case 0x02: return OF_OXM_BSN_LAG_ID;
536 case 0x03: return OF_OXM_BSN_LAG_ID_MASKED;
Rich Laneeb21c4f2013-10-28 17:34:41 -0700537 case 0x04: return OF_OXM_BSN_VRF;
538 case 0x05: return OF_OXM_BSN_VRF_MASKED;
539 case 0x06: return OF_OXM_BSN_GLOBAL_VRF_ALLOWED;
540 case 0x07: return OF_OXM_BSN_GLOBAL_VRF_ALLOWED_MASKED;
541 case 0x08: return OF_OXM_BSN_L3_INTERFACE_CLASS_ID;
542 case 0x09: return OF_OXM_BSN_L3_INTERFACE_CLASS_ID_MASKED;
543 case 0x0a: return OF_OXM_BSN_L3_SRC_CLASS_ID;
544 case 0x0b: return OF_OXM_BSN_L3_SRC_CLASS_ID_MASKED;
545 case 0x0c: return OF_OXM_BSN_L3_DST_CLASS_ID;
546 case 0x0d: return OF_OXM_BSN_L3_DST_CLASS_ID_MASKED;
Rich Laned8d29c92013-09-24 13:46:42 -0700547 default: return OF_OBJECT_INVALID;
548 }
549 } else {
550 return OF_OBJECT_INVALID;
551 }
552}
553"""
554
Rich Lanea06d0c32013-03-25 08:52:03 -0700555 # Action types array gen
556 ar_len = type_maps.type_array_len(type_maps.action_types, max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700557 out.write(map_with_experimenter_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700558 dict(name="action", u_name="ACTION", ar_len=ar_len))
559
560 # Action ID types array gen
561 ar_len = type_maps.type_array_len(type_maps.action_id_types, max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700562 out.write(map_with_experimenter_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700563 dict(name="action_id", u_name="ACTION_ID", ar_len=ar_len))
564
565 # Instruction types array gen
566 ar_len = type_maps.type_array_len(type_maps.instruction_types,
567 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700568 out.write(map_with_experimenter_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700569 dict(name="instruction", u_name="INSTRUCTION", ar_len=ar_len))
570
Jonathan Stout83cedcc2014-03-03 16:38:00 -0500571 # Instruction ID types array gen
572 ar_len = type_maps.type_array_len(type_maps.instruction_id_types, max_type_value)
573 out.write(map_with_experimenter_template %
574 dict(name="instruction_id", u_name="INSTRUCTION_ID", ar_len=ar_len))
575
Rich Lanea06d0c32013-03-25 08:52:03 -0700576 # Queue prop types array gen
577 ar_len = type_maps.type_array_len(type_maps.queue_prop_types,
578 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700579 out.write(map_with_experimenter_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700580 dict(name="queue_prop", u_name="QUEUE_PROP", ar_len=ar_len))
581
582 # Table feature prop types array gen
583 ar_len = type_maps.type_array_len(type_maps.table_feature_prop_types,
584 max_type_value)
Jonathan Stout9f17b4b2014-02-14 11:56:37 -0500585 out.write(table_features_prop_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700586 dict(name="table_feature_prop", u_name="TABLE_FEATURE_PROP",
587 ar_len=ar_len))
588
589 # Meter band types array gen
590 ar_len = type_maps.type_array_len(type_maps.meter_band_types,
591 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700592 out.write(map_with_experimenter_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700593 dict(name="meter_band", u_name="METER_BAND", ar_len=ar_len))
594
595 # Hello elem types array gen
596 ar_len = type_maps.type_array_len(type_maps.hello_elem_types,
597 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700598 out.write(map_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700599 dict(name="hello_elem", u_name="HELLO_ELEM", ar_len=ar_len))
600
601 # Stats types array gen
602 ar_len = type_maps.type_array_len(type_maps.stats_types,
603 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700604 out.write(stats_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700605 dict(name="stats_reply", u_name="STATS_REPLY", ar_len=ar_len))
Andreas Wundsam53256162013-05-02 14:05:53 -0700606 out.write(stats_template %
607 dict(name="stats_request", u_name="STATS_REQUEST",
Rich Lanea06d0c32013-03-25 08:52:03 -0700608 ar_len=ar_len))
609
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700610 ar_len = type_maps.type_array_len(type_maps.error_types,
611 max_type_value)
612 out.write(error_msg_template %
613 dict(name="error_msg", u_name="ERROR_MSG", ar_len=ar_len))
614# out.write(error_msg_function)
615
Rich Lanea06d0c32013-03-25 08:52:03 -0700616 ar_len = type_maps.type_array_len(type_maps.flow_mod_types, max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700617 out.write(map_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700618 dict(name="flow_mod", u_name="FLOW_MOD", ar_len=ar_len))
619
Rich Lanee3113672013-12-06 17:09:57 -0800620 ar_len = type_maps.type_array_len(type_maps.group_mod_types,
621 max_type_value)
622 out.write(map_template %
623 dict(name="group_mod", u_name="GROUP_MOD", ar_len=ar_len))
624
Rich Laned8d29c92013-09-24 13:46:42 -0700625 # OXM
Rich Lanea06d0c32013-03-25 08:52:03 -0700626 ar_len = type_maps.type_array_len(type_maps.oxm_types, max_type_value)
627 out.write("""
628/* NOTE: We could optimize the OXM and only generate OF 1.2 versions. */
629""")
Rich Laned8d29c92013-09-24 13:46:42 -0700630 out.write(oxm_template % dict(ar_len=ar_len))
Rich Lanea06d0c32013-03-25 08:52:03 -0700631
Rich Laned8d29c92013-09-24 13:46:42 -0700632 # Messages
Rich Lanea06d0c32013-03-25 08:52:03 -0700633 out.write(experimenter_function)
634 # Must follow stats reply/request
635 ar_len = type_maps.type_array_len(type_maps.message_types, max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700636 out.write(msg_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700637 dict(name="message", u_name="MESSAGE", ar_len=ar_len))
638
Rich Lane713d9282013-12-30 15:21:35 -0800639 # BSN TLV elem types array gen
640 ar_len = type_maps.type_array_len(type_maps.bsn_tlv_types,
641 max_type_value)
642 out.write(map_template %
643 dict(name="bsn_tlv", u_name="BSN_TLV", ar_len=ar_len))
644
Rich Lanea06d0c32013-03-25 08:52:03 -0700645def gen_type_data_header(out):
646
647 out.write("""
648/****************************************************************
649 *
650 * The following declarations are for type and length calculations.
651 * Implementations may be found in of_type_maps.c
652 *
653 ****************************************************************/
654/*
655 * Special case length functions for objects with
656 */
657""")
658 for ((cls, name), prev) in of_g.special_offsets.items():
659 s_cls = cls[3:] # take off of_
660 out.write("""
661/**
662 * Special length calculation for %(cls)s->%(name)s.
Andreas Wundsam53256162013-05-02 14:05:53 -0700663 * @param obj An object of type %(cls)s to check for
Rich Lanea06d0c32013-03-25 08:52:03 -0700664 * length of %(name)s
665 * @param bytes[out] Where to store the calculated length
666 *
667 * Preceding data member is %(prev)s.
668 */
669extern int of_length_%(s_cls)s_%(name)s_get(
670 %(cls)s_t *obj, int *bytes);
671
672/**
673 * Special offset calculation for %(cls)s->%(name)s.
Andreas Wundsam53256162013-05-02 14:05:53 -0700674 * @param obj An object of type %(cls)s to check for
Rich Lanea06d0c32013-03-25 08:52:03 -0700675 * length of %(name)s
676 * @param offset[out] Where to store the calculated length
677 *
678 * Preceding data member is %(prev)s.
679 */
680extern int of_offset_%(s_cls)s_%(name)s_get(
681 %(cls)s_t *obj, int *offset);
682""" % dict(cls=cls, s_cls=s_cls, name=name, prev=prev))
683
684# NOT NEEDED YET
685# # For non-message, variable length objects, give a fun that
686# # calculates the length
687# for cls in of_g.standard_class_order:
688# s_cls = cls[3:] # take off of_
689# if !type_is_var_len(cls, version):
690# continue
691# out.write("""
692# /**
693# * Special length calculation for variable length object %(cls)s
694# * @param obj An object of type %(cls)s whose length is being calculated
695# * @param bytes[out] Where to store the calculated length
696# *
697# * The assumption is that the length member of the object is not
698# * valid and the length needs to be calculated from other information
699# * such as the parent.
700# */
701# extern int of_length_%(s_cls)s_get(
702# %(cls)s_t *obj, int *bytes);
Andreas Wundsam53256162013-05-02 14:05:53 -0700703# """ % dict(cls=cls, s_cls=s_cls))
Rich Lanea06d0c32013-03-25 08:52:03 -0700704
705 out.write("""
706/****************************************************************
707 * Wire type/length functions.
708 ****************************************************************/
709
710extern void of_object_message_wire_length_get(of_object_t *obj, int *bytes);
711extern void of_object_message_wire_length_set(of_object_t *obj, int bytes);
712
713extern void of_oxm_wire_length_get(of_object_t *obj, int *bytes);
Rich Lanea06d0c32013-03-25 08:52:03 -0700714extern void of_oxm_wire_object_id_get(of_object_t *obj, of_object_id_t *id);
Rich Lanea06d0c32013-03-25 08:52:03 -0700715
716extern void of_tlv16_wire_length_get(of_object_t *obj, int *bytes);
717extern void of_tlv16_wire_length_set(of_object_t *obj, int bytes);
718
Rich Lanea06d0c32013-03-25 08:52:03 -0700719/* Wire length is uint16 at front of structure */
720extern void of_u16_len_wire_length_get(of_object_t *obj, int *bytes);
721extern void of_u16_len_wire_length_set(of_object_t *obj, int bytes);
722
723extern void of_action_wire_object_id_get(of_object_t *obj, of_object_id_t *id);
724extern void of_action_id_wire_object_id_get(of_object_t *obj, of_object_id_t *id);
Andreas Wundsam53256162013-05-02 14:05:53 -0700725extern void of_instruction_wire_object_id_get(of_object_t *obj,
Rich Lanea06d0c32013-03-25 08:52:03 -0700726 of_object_id_t *id);
Jonathan Stout83cedcc2014-03-03 16:38:00 -0500727extern void of_instruction_id_wire_object_id_get(of_object_t *obj,
728 of_object_id_t *id);
Andreas Wundsam53256162013-05-02 14:05:53 -0700729extern void of_queue_prop_wire_object_id_get(of_object_t *obj,
Rich Lanea06d0c32013-03-25 08:52:03 -0700730 of_object_id_t *id);
Andreas Wundsam53256162013-05-02 14:05:53 -0700731extern void of_table_feature_prop_wire_object_id_get(of_object_t *obj,
Rich Lanea06d0c32013-03-25 08:52:03 -0700732 of_object_id_t *id);
Andreas Wundsam53256162013-05-02 14:05:53 -0700733extern void of_meter_band_wire_object_id_get(of_object_t *obj,
Rich Lanea06d0c32013-03-25 08:52:03 -0700734 of_object_id_t *id);
Andreas Wundsam53256162013-05-02 14:05:53 -0700735extern void of_hello_elem_wire_object_id_get(of_object_t *obj,
Rich Lanea06d0c32013-03-25 08:52:03 -0700736 of_object_id_t *id);
Rich Lane713d9282013-12-30 15:21:35 -0800737extern void of_bsn_tlv_wire_object_id_get(of_object_t *obj,
738 of_object_id_t *id);
Rich Lanea06d0c32013-03-25 08:52:03 -0700739
Rich Lane47085722013-07-12 16:27:04 -0700740#define OF_OXM_LENGTH_GET(hdr) (((hdr) & 0xff) + 4)
Rich Lanea06d0c32013-03-25 08:52:03 -0700741#define OF_OXM_LENGTH_SET(hdr, val) \\
Rich Lane47085722013-07-12 16:27:04 -0700742 (hdr) = ((hdr) & 0xffffff00) + (((val) - 4) & 0xff)
Rich Lanea06d0c32013-03-25 08:52:03 -0700743
744extern void of_packet_queue_wire_length_get(of_object_t *obj, int *bytes);
745extern void of_packet_queue_wire_length_set(of_object_t *obj, int bytes);
746
747extern void of_list_meter_band_stats_wire_length_get(of_object_t *obj,
748 int *bytes);
749extern void of_meter_stats_wire_length_get(of_object_t *obj, int *bytes);
750extern void of_meter_stats_wire_length_set(of_object_t *obj, int bytes);
751extern int of_extension_object_wire_push(of_object_t *obj);
752
753""")
754
755
756def gen_length_array(out):
757 """
758 Generate an array giving the lengths of all objects/versions
759 @param out The file handle to which to write
760 """
761 out.write("""
762/**
763 * An array with the number of bytes in the fixed length part
764 * of each OF object
765 */
766""")
767
768 for version in of_g.of_version_range:
769 out.write("""
Rich Laneb157b0f2013-03-27 13:55:28 -0700770static const int\nof_object_fixed_len_v%d[OF_OBJECT_COUNT] = {
Rich Lanea06d0c32013-03-25 08:52:03 -0700771 -1, /* of_object is not instantiable */
772""" % version)
773 for i, cls in enumerate(of_g.all_class_order):
774 comma = ","
775 if i == len(of_g.all_class_order) - 1:
776 comma = ""
777 val = "-1" + comma
778 if (cls, version) in of_g.base_length:
779 val = str(of_g.base_length[(cls, version)]) + comma
780 out.write(" %-5s /* %d: %s */\n" % (val, i + 1, cls))
781 out.write("};\n")
782
783 out.write("""
784/**
785 * Unified map of fixed length part of each object
786 */
Rich Laneb157b0f2013-03-27 13:55:28 -0700787const int *const of_object_fixed_len[OF_VERSION_ARRAY_MAX] = {
Rich Lanea06d0c32013-03-25 08:52:03 -0700788 NULL,
789""")
790 for version in of_g.of_version_range:
791 out.write(" of_object_fixed_len_v%d,\n" % version)
792 out.write("""
793};
794""")
795
Andreas Wundsam53256162013-05-02 14:05:53 -0700796
Rich Lanef70be942013-07-18 13:33:14 -0700797def gen_extra_length_array(out):
798 """
799 Generate an array giving the extra lengths of all objects/versions
800 @param out The file handle to which to write
801 """
802 out.write("""
803/**
804 * An array with the number of bytes in the extra length part
805 * of each OF object
806 */
807""")
808
809 for version in of_g.of_version_range:
810 out.write("""
811static const int\nof_object_extra_len_v%d[OF_OBJECT_COUNT] = {
812 -1, /* of_object is not instantiable */
813""" % version)
814 for i, cls in enumerate(of_g.all_class_order):
815 comma = ","
816 if i == len(of_g.all_class_order) - 1:
817 comma = ""
818 val = "-1" + comma
819 if (cls, version) in of_g.base_length:
820 val = str(of_g.extra_length.get((cls, version), 0)) + comma
821 out.write(" %-5s /* %d: %s */\n" % (val, i + 1, cls))
822 out.write("};\n")
823
824 out.write("""
825/**
826 * Unified map of extra length part of each object
827 */
828const int *const of_object_extra_len[OF_VERSION_ARRAY_MAX] = {
829 NULL,
830""")
831 for version in of_g.of_version_range:
832 out.write(" of_object_extra_len_v%d,\n" % version)
833 out.write("""
834};
835""")