blob: 6e6f3fedb2f5f42157be8512fd8275b8e540d155 [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 Stoutc26cbdb2014-03-04 12:46:17 -0500121 gen_type_to_object_id(out, "instruction_id_type_to_id", "OF_INSTRUCTION_ID",
Jonathan Stout83cedcc2014-03-03 16:38:00 -0500122 "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"""
Rich Lanea06d0c32013-03-25 08:52:03 -0700370 for version, experimenter_lists in type_maps.extension_message_subtype.items():
371 for exp, subtypes in experimenter_lists.items():
372 experimenter_function += """
Andreas Wundsam53256162013-05-02 14:05:53 -0700373 if ((experimenter_id == OF_EXPERIMENTER_ID_%(exp_name)s) &&
Rich Lanea06d0c32013-03-25 08:52:03 -0700374 (version == %(ver_name)s)) {
375""" % dict(exp_name=exp.upper(), ver_name=of_g.wire_ver_map[version])
376 for ext_msg, subtype in subtypes.items():
377 experimenter_function += """
378 if (subtype == %(subtype)s) {
379 return %(ext_msg)s;
380 }
381""" % dict(subtype=subtype, ext_msg=ext_msg.upper())
382 experimenter_function += """
383 }
384"""
385 experimenter_function += """
386 return OF_EXPERIMENTER;
387}
388"""
389
390 # Message need different handling
391 msg_template = """
392/**
393 * %(name)s wire type to object ID array.
394 * Treat as private; use function accessor below
395 */
396
Rich Laneb157b0f2013-03-27 13:55:28 -0700397extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];
Rich Lanea06d0c32013-03-25 08:52:03 -0700398
399#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n
400
401/**
402 * Extract the type info from the message and determine its object type
403 * @param msg An OF message object (uint8_t *)
404 * @param length The number of bytes in the message (for error checking)
405 * @returns object ID or OF_OBJECT_INVALID if parse error
406 */
407
Rich Lanec0e20ff2013-12-15 23:40:31 -0800408of_object_id_t
Rich Lanea06d0c32013-03-25 08:52:03 -0700409of_message_to_object_id(of_message_t msg, int length) {
410 uint8_t type;
411 of_version_t ver;
412 of_object_id_t obj_id;
413 uint16_t stats_type;
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700414 uint16_t err_type;
Rich Lanea06d0c32013-03-25 08:52:03 -0700415 uint8_t flow_mod_cmd;
Rich Lane353a79f2013-11-13 10:39:56 -0800416 uint32_t experimenter, subtype;
Rich Lanee3113672013-12-06 17:09:57 -0800417 uint16_t group_mod_cmd;
Rich Lanea06d0c32013-03-25 08:52:03 -0700418
419 if (length < OF_MESSAGE_MIN_LENGTH) {
420 return OF_OBJECT_INVALID;
421 }
422 type = of_message_type_get(msg);
423 ver = of_message_version_get(msg);
424 if (!OF_VERSION_OKAY(ver)) {
425 return OF_OBJECT_INVALID;
426 }
427
428 if (type >= OF_MESSAGE_ITEM_COUNT) {
429 return OF_OBJECT_INVALID;
430 }
431
432 obj_id = of_message_type_to_id[ver][type];
433
434 /* Remap to specific message if known */
435 if (obj_id == OF_EXPERIMENTER) {
436 if (length < OF_MESSAGE_EXPERIMENTER_MIN_LENGTH) {
437 return OF_OBJECT_INVALID;
438 }
439 return of_message_experimenter_to_object_id(msg, ver);
440 }
441
442 /* Remap to add/delete/strict version */
443 if (obj_id == OF_FLOW_MOD) {
444 if (length < OF_MESSAGE_MIN_FLOW_MOD_LENGTH(ver)) {
445 return OF_OBJECT_INVALID;
446 }
447 flow_mod_cmd = of_message_flow_mod_command_get(msg, ver);
448 obj_id = of_flow_mod_to_object_id(flow_mod_cmd, ver);
449 }
450
451 if ((obj_id == OF_STATS_REQUEST) || (obj_id == OF_STATS_REPLY)) {
452 if (length < OF_MESSAGE_MIN_STATS_LENGTH) {
453 return OF_OBJECT_INVALID;
454 }
455 stats_type = of_message_stats_type_get(msg);
Rich Lane353a79f2013-11-13 10:39:56 -0800456 if (stats_type == OF_STATS_TYPE_EXPERIMENTER) {
457 if (length < OF_MESSAGE_STATS_EXPERIMENTER_MIN_LENGTH) {
458 return OF_OBJECT_INVALID;
459 }
460 experimenter = of_message_stats_experimenter_id_get(msg);
461 subtype = of_message_stats_experimenter_subtype_get(msg);
462 if (obj_id == OF_STATS_REQUEST) {
463 obj_id = of_experimenter_stats_request_to_object_id(experimenter, subtype, ver);
464 } else {
465 obj_id = of_experimenter_stats_reply_to_object_id(experimenter, subtype, ver);
466 }
Rich Lanea06d0c32013-03-25 08:52:03 -0700467 } else {
Rich Lane353a79f2013-11-13 10:39:56 -0800468 if (obj_id == OF_STATS_REQUEST) {
469 obj_id = of_stats_request_to_object_id(stats_type, ver);
470 } else {
471 obj_id = of_stats_reply_to_object_id(stats_type, ver);
472 }
Rich Lanea06d0c32013-03-25 08:52:03 -0700473 }
474 }
475
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700476 if (obj_id == OF_ERROR_MSG) {
477 if (length < OF_MESSAGE_MIN_ERROR_LENGTH) {
478 return OF_OBJECT_INVALID;
479 }
480 err_type = of_message_error_type_get(msg);
481 obj_id = of_error_msg_to_object_id(err_type, ver);
482 }
483
Rich Lanee3113672013-12-06 17:09:57 -0800484 if (obj_id == OF_GROUP_MOD) {
485 if (length < OF_MESSAGE_MIN_GROUP_MOD_LENGTH) {
486 return OF_OBJECT_INVALID;
487 }
488 group_mod_cmd = of_message_group_mod_command_get(msg);
489 obj_id = of_group_mod_to_object_id(group_mod_cmd, ver);
490 }
491
Rich Lanea06d0c32013-03-25 08:52:03 -0700492 return obj_id;
493}
494"""
495
Rich Laned8d29c92013-09-24 13:46:42 -0700496 oxm_template = """
497/**
498 * oxm wire type to object ID array.
499 * Treat as private; use function accessor below
500 */
501
502extern const of_object_id_t *const of_oxm_type_to_id[OF_VERSION_ARRAY_MAX];
503
504#define OF_OXM_ITEM_COUNT %(ar_len)d\n
505
506/**
507 * Map an oxm wire value to an OF object
508 * @param oxm The oxm type wire value
509 * @param version The version associated with the check
510 * @return The oxm OF object type
511 * @return OF_OBJECT_INVALID if type does not map to an object
512 *
513 */
Rich Lanec0e20ff2013-12-15 23:40:31 -0800514of_object_id_t
Rich Laned8d29c92013-09-24 13:46:42 -0700515of_oxm_to_object_id(uint32_t type_len, of_version_t version)
516{
517 if (!OF_VERSION_OKAY(version)) {
518 return OF_OBJECT_INVALID;
519 }
520
521 uint16_t class = (type_len >> 16) & 0xffff;
522 uint8_t masked_type = (type_len >> 8) & 0xff;
523
524 if (class == 0x8000) {
525 if (masked_type < 0 || masked_type >= OF_OXM_ITEM_COUNT) {
526 return OF_OBJECT_INVALID;
527 }
528
529 return of_oxm_type_to_id[version][masked_type];
530 } else if (class == 0x0003) {
531 switch (masked_type) {
532 case 0x00: return OF_OXM_BSN_IN_PORTS_128;
533 case 0x01: return OF_OXM_BSN_IN_PORTS_128_MASKED;
Rich Lane61718362013-10-24 16:59:42 -0700534 case 0x02: return OF_OXM_BSN_LAG_ID;
535 case 0x03: return OF_OXM_BSN_LAG_ID_MASKED;
Rich Laneeb21c4f2013-10-28 17:34:41 -0700536 case 0x04: return OF_OXM_BSN_VRF;
537 case 0x05: return OF_OXM_BSN_VRF_MASKED;
538 case 0x06: return OF_OXM_BSN_GLOBAL_VRF_ALLOWED;
539 case 0x07: return OF_OXM_BSN_GLOBAL_VRF_ALLOWED_MASKED;
540 case 0x08: return OF_OXM_BSN_L3_INTERFACE_CLASS_ID;
541 case 0x09: return OF_OXM_BSN_L3_INTERFACE_CLASS_ID_MASKED;
542 case 0x0a: return OF_OXM_BSN_L3_SRC_CLASS_ID;
543 case 0x0b: return OF_OXM_BSN_L3_SRC_CLASS_ID_MASKED;
544 case 0x0c: return OF_OXM_BSN_L3_DST_CLASS_ID;
545 case 0x0d: return OF_OXM_BSN_L3_DST_CLASS_ID_MASKED;
Rich Lane53ddf5c2014-03-20 15:24:08 -0700546 case 0x10: return OF_OXM_BSN_UDF0;
547 case 0x11: return OF_OXM_BSN_UDF0_MASKED;
548 case 0x12: return OF_OXM_BSN_UDF1;
549 case 0x13: return OF_OXM_BSN_UDF1_MASKED;
550 case 0x14: return OF_OXM_BSN_UDF2;
551 case 0x15: return OF_OXM_BSN_UDF2_MASKED;
552 case 0x16: return OF_OXM_BSN_UDF3;
553 case 0x17: return OF_OXM_BSN_UDF3_MASKED;
554 case 0x18: return OF_OXM_BSN_UDF4;
555 case 0x19: return OF_OXM_BSN_UDF4_MASKED;
556 case 0x1a: return OF_OXM_BSN_UDF5;
557 case 0x1b: return OF_OXM_BSN_UDF5_MASKED;
558 case 0x1c: return OF_OXM_BSN_UDF6;
559 case 0x1d: return OF_OXM_BSN_UDF6_MASKED;
560 case 0x1e: return OF_OXM_BSN_UDF7;
561 case 0x1f: return OF_OXM_BSN_UDF7_MASKED;
Rich Laned8d29c92013-09-24 13:46:42 -0700562 default: return OF_OBJECT_INVALID;
563 }
564 } else {
565 return OF_OBJECT_INVALID;
566 }
567}
568"""
569
Rich Lanea06d0c32013-03-25 08:52:03 -0700570 # Action types array gen
571 ar_len = type_maps.type_array_len(type_maps.action_types, max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700572 out.write(map_with_experimenter_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700573 dict(name="action", u_name="ACTION", ar_len=ar_len))
574
575 # Action ID types array gen
576 ar_len = type_maps.type_array_len(type_maps.action_id_types, max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700577 out.write(map_with_experimenter_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700578 dict(name="action_id", u_name="ACTION_ID", ar_len=ar_len))
579
580 # Instruction types array gen
581 ar_len = type_maps.type_array_len(type_maps.instruction_types,
582 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700583 out.write(map_with_experimenter_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700584 dict(name="instruction", u_name="INSTRUCTION", ar_len=ar_len))
585
Jonathan Stout83cedcc2014-03-03 16:38:00 -0500586 # Instruction ID types array gen
587 ar_len = type_maps.type_array_len(type_maps.instruction_id_types, max_type_value)
588 out.write(map_with_experimenter_template %
589 dict(name="instruction_id", u_name="INSTRUCTION_ID", ar_len=ar_len))
590
Rich Lanea06d0c32013-03-25 08:52:03 -0700591 # Queue prop types array gen
592 ar_len = type_maps.type_array_len(type_maps.queue_prop_types,
593 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700594 out.write(map_with_experimenter_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700595 dict(name="queue_prop", u_name="QUEUE_PROP", ar_len=ar_len))
596
597 # Table feature prop types array gen
598 ar_len = type_maps.type_array_len(type_maps.table_feature_prop_types,
599 max_type_value)
Jonathan Stout9f17b4b2014-02-14 11:56:37 -0500600 out.write(table_features_prop_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700601 dict(name="table_feature_prop", u_name="TABLE_FEATURE_PROP",
602 ar_len=ar_len))
603
604 # Meter band types array gen
605 ar_len = type_maps.type_array_len(type_maps.meter_band_types,
606 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700607 out.write(map_with_experimenter_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700608 dict(name="meter_band", u_name="METER_BAND", ar_len=ar_len))
609
610 # Hello elem types array gen
611 ar_len = type_maps.type_array_len(type_maps.hello_elem_types,
612 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700613 out.write(map_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700614 dict(name="hello_elem", u_name="HELLO_ELEM", ar_len=ar_len))
615
616 # Stats types array gen
617 ar_len = type_maps.type_array_len(type_maps.stats_types,
618 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700619 out.write(stats_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700620 dict(name="stats_reply", u_name="STATS_REPLY", ar_len=ar_len))
Andreas Wundsam53256162013-05-02 14:05:53 -0700621 out.write(stats_template %
622 dict(name="stats_request", u_name="STATS_REQUEST",
Rich Lanea06d0c32013-03-25 08:52:03 -0700623 ar_len=ar_len))
624
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700625 ar_len = type_maps.type_array_len(type_maps.error_types,
626 max_type_value)
627 out.write(error_msg_template %
628 dict(name="error_msg", u_name="ERROR_MSG", ar_len=ar_len))
629# out.write(error_msg_function)
630
Rich Lanea06d0c32013-03-25 08:52:03 -0700631 ar_len = type_maps.type_array_len(type_maps.flow_mod_types, max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700632 out.write(map_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700633 dict(name="flow_mod", u_name="FLOW_MOD", ar_len=ar_len))
634
Rich Lanee3113672013-12-06 17:09:57 -0800635 ar_len = type_maps.type_array_len(type_maps.group_mod_types,
636 max_type_value)
637 out.write(map_template %
638 dict(name="group_mod", u_name="GROUP_MOD", ar_len=ar_len))
639
Rich Laned8d29c92013-09-24 13:46:42 -0700640 # OXM
Rich Lanea06d0c32013-03-25 08:52:03 -0700641 ar_len = type_maps.type_array_len(type_maps.oxm_types, max_type_value)
642 out.write("""
643/* NOTE: We could optimize the OXM and only generate OF 1.2 versions. */
644""")
Rich Laned8d29c92013-09-24 13:46:42 -0700645 out.write(oxm_template % dict(ar_len=ar_len))
Rich Lanea06d0c32013-03-25 08:52:03 -0700646
Rich Laned8d29c92013-09-24 13:46:42 -0700647 # Messages
Rich Lanea06d0c32013-03-25 08:52:03 -0700648 out.write(experimenter_function)
649 # Must follow stats reply/request
650 ar_len = type_maps.type_array_len(type_maps.message_types, max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700651 out.write(msg_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700652 dict(name="message", u_name="MESSAGE", ar_len=ar_len))
653
Rich Lane713d9282013-12-30 15:21:35 -0800654 # BSN TLV elem types array gen
655 ar_len = type_maps.type_array_len(type_maps.bsn_tlv_types,
656 max_type_value)
657 out.write(map_template %
658 dict(name="bsn_tlv", u_name="BSN_TLV", ar_len=ar_len))
659
Rich Lanea06d0c32013-03-25 08:52:03 -0700660def gen_type_data_header(out):
661
662 out.write("""
663/****************************************************************
664 *
665 * The following declarations are for type and length calculations.
666 * Implementations may be found in of_type_maps.c
667 *
668 ****************************************************************/
669/*
670 * Special case length functions for objects with
671 */
672""")
673 for ((cls, name), prev) in of_g.special_offsets.items():
674 s_cls = cls[3:] # take off of_
675 out.write("""
676/**
677 * Special length calculation for %(cls)s->%(name)s.
Andreas Wundsam53256162013-05-02 14:05:53 -0700678 * @param obj An object of type %(cls)s to check for
Rich Lanea06d0c32013-03-25 08:52:03 -0700679 * length of %(name)s
680 * @param bytes[out] Where to store the calculated length
681 *
682 * Preceding data member is %(prev)s.
683 */
684extern int of_length_%(s_cls)s_%(name)s_get(
685 %(cls)s_t *obj, int *bytes);
686
687/**
688 * Special offset calculation for %(cls)s->%(name)s.
Andreas Wundsam53256162013-05-02 14:05:53 -0700689 * @param obj An object of type %(cls)s to check for
Rich Lanea06d0c32013-03-25 08:52:03 -0700690 * length of %(name)s
691 * @param offset[out] Where to store the calculated length
692 *
693 * Preceding data member is %(prev)s.
694 */
695extern int of_offset_%(s_cls)s_%(name)s_get(
696 %(cls)s_t *obj, int *offset);
697""" % dict(cls=cls, s_cls=s_cls, name=name, prev=prev))
698
699# NOT NEEDED YET
700# # For non-message, variable length objects, give a fun that
701# # calculates the length
702# for cls in of_g.standard_class_order:
703# s_cls = cls[3:] # take off of_
704# if !type_is_var_len(cls, version):
705# continue
706# out.write("""
707# /**
708# * Special length calculation for variable length object %(cls)s
709# * @param obj An object of type %(cls)s whose length is being calculated
710# * @param bytes[out] Where to store the calculated length
711# *
712# * The assumption is that the length member of the object is not
713# * valid and the length needs to be calculated from other information
714# * such as the parent.
715# */
716# extern int of_length_%(s_cls)s_get(
717# %(cls)s_t *obj, int *bytes);
Andreas Wundsam53256162013-05-02 14:05:53 -0700718# """ % dict(cls=cls, s_cls=s_cls))
Rich Lanea06d0c32013-03-25 08:52:03 -0700719
720 out.write("""
721/****************************************************************
722 * Wire type/length functions.
723 ****************************************************************/
724
725extern void of_object_message_wire_length_get(of_object_t *obj, int *bytes);
726extern void of_object_message_wire_length_set(of_object_t *obj, int bytes);
727
728extern void of_oxm_wire_length_get(of_object_t *obj, int *bytes);
Rich Lanea06d0c32013-03-25 08:52:03 -0700729
730extern void of_tlv16_wire_length_get(of_object_t *obj, int *bytes);
731extern void of_tlv16_wire_length_set(of_object_t *obj, int bytes);
732
Rich Lanea06d0c32013-03-25 08:52:03 -0700733/* Wire length is uint16 at front of structure */
734extern void of_u16_len_wire_length_get(of_object_t *obj, int *bytes);
735extern void of_u16_len_wire_length_set(of_object_t *obj, int bytes);
736
Rich Lane47085722013-07-12 16:27:04 -0700737#define OF_OXM_LENGTH_GET(hdr) (((hdr) & 0xff) + 4)
Rich Lanea06d0c32013-03-25 08:52:03 -0700738#define OF_OXM_LENGTH_SET(hdr, val) \\
Rich Lane47085722013-07-12 16:27:04 -0700739 (hdr) = ((hdr) & 0xffffff00) + (((val) - 4) & 0xff)
Rich Lanea06d0c32013-03-25 08:52:03 -0700740
741extern void of_packet_queue_wire_length_get(of_object_t *obj, int *bytes);
742extern void of_packet_queue_wire_length_set(of_object_t *obj, int bytes);
743
744extern void of_list_meter_band_stats_wire_length_get(of_object_t *obj,
745 int *bytes);
746extern void of_meter_stats_wire_length_get(of_object_t *obj, int *bytes);
747extern void of_meter_stats_wire_length_set(of_object_t *obj, int bytes);
Rich Lanea06d0c32013-03-25 08:52:03 -0700748
749""")
750
751
752def gen_length_array(out):
753 """
754 Generate an array giving the lengths of all objects/versions
755 @param out The file handle to which to write
756 """
757 out.write("""
758/**
759 * An array with the number of bytes in the fixed length part
760 * of each OF object
761 */
762""")
763
764 for version in of_g.of_version_range:
765 out.write("""
Rich Laneb157b0f2013-03-27 13:55:28 -0700766static const int\nof_object_fixed_len_v%d[OF_OBJECT_COUNT] = {
Rich Lanea06d0c32013-03-25 08:52:03 -0700767 -1, /* of_object is not instantiable */
768""" % version)
769 for i, cls in enumerate(of_g.all_class_order):
770 comma = ","
771 if i == len(of_g.all_class_order) - 1:
772 comma = ""
773 val = "-1" + comma
774 if (cls, version) in of_g.base_length:
775 val = str(of_g.base_length[(cls, version)]) + comma
776 out.write(" %-5s /* %d: %s */\n" % (val, i + 1, cls))
777 out.write("};\n")
778
779 out.write("""
780/**
781 * Unified map of fixed length part of each object
782 */
Rich Laneb157b0f2013-03-27 13:55:28 -0700783const int *const of_object_fixed_len[OF_VERSION_ARRAY_MAX] = {
Rich Lanea06d0c32013-03-25 08:52:03 -0700784 NULL,
785""")
786 for version in of_g.of_version_range:
787 out.write(" of_object_fixed_len_v%d,\n" % version)
788 out.write("""
789};
790""")
791
Andreas Wundsam53256162013-05-02 14:05:53 -0700792
Rich Lanef70be942013-07-18 13:33:14 -0700793def gen_extra_length_array(out):
794 """
795 Generate an array giving the extra lengths of all objects/versions
796 @param out The file handle to which to write
797 """
798 out.write("""
799/**
800 * An array with the number of bytes in the extra length part
801 * of each OF object
802 */
803""")
804
805 for version in of_g.of_version_range:
806 out.write("""
807static const int\nof_object_extra_len_v%d[OF_OBJECT_COUNT] = {
808 -1, /* of_object is not instantiable */
809""" % version)
810 for i, cls in enumerate(of_g.all_class_order):
811 comma = ","
812 if i == len(of_g.all_class_order) - 1:
813 comma = ""
814 val = "-1" + comma
815 if (cls, version) in of_g.base_length:
816 val = str(of_g.extra_length.get((cls, version), 0)) + comma
817 out.write(" %-5s /* %d: %s */\n" % (val, i + 1, cls))
818 out.write("};\n")
819
820 out.write("""
821/**
822 * Unified map of extra length part of each object
823 */
824const int *const of_object_extra_len[OF_VERSION_ARRAY_MAX] = {
825 NULL,
826""")
827 for version in of_g.of_version_range:
828 out.write(" of_object_extra_len_v%d,\n" % version)
829 out.write("""
830};
831""")