blob: 9ad6608b59bf3abcaf946c5fd399043cfd750fa9 [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 """
Jonathan Stoutc26cbdb2014-03-04 12:46:17 -050050 if type_str == "instruction_id_type_to_id" or \
51 type_str == "instruction_type_to_id":
52 print prefix
53 print value_array
54
Rich Lanea06d0c32013-03-25 08:52:03 -070055
56 # Create unified arrays and get length
57 arr_len = type_maps.type_array_len(value_array, max_val)
58 all_ars = []
59 for version, val_dict in value_array.items(): # Per version dict
60 ar = type_maps.dict_to_array(val_dict, max_val, type_maps.invalid_type)
61 all_ars.append(ar)
62
63 len_name = "%s_ITEM_COUNT" % prefix
64
65 for i, ar in enumerate(all_ars):
66 version = i + 1
Rich Laneb157b0f2013-03-27 13:55:28 -070067 out.write("static const of_object_id_t\nof_%s_v%d[%s] = {\n" %
Rich Lanea06d0c32013-03-25 08:52:03 -070068 (type_str, version, len_name))
69 for i in range(arr_len):
70 comma = ""
71 if i < arr_len - 1: # Avoid ultimate comma
72 comma = ","
73
74 # Per-version length check
75 if i < len(ar):
76 v = ar[i]
77 else:
78 v = type_maps.invalid_type
79
80 if v == type_maps.invalid_type:
81 out.write(" %-30s /* %d (Invalid) */\n" %
82 ("OF_OBJECT_INVALID" + comma, i))
83 else:
84 name = (template % v.upper()) + comma
85 out.write(" %-30s /* %d */\n" % (name, i))
86 out.write("};\n")
87
88 out.write("""
89/**
90 * Maps from %(c_name)s wire type values to LOCI object ids
91 *
92 * Indexed by wire version which is 1-based.
93 */
94
Rich Laneb157b0f2013-03-27 13:55:28 -070095const of_object_id_t *const of_%(name)s[OF_VERSION_ARRAY_MAX] = {
Rich Lanea06d0c32013-03-25 08:52:03 -070096 NULL,
97""" % dict(name=type_str, c_name=prefix.lower()))
98 for version in of_g.of_version_range:
99 out.write(" of_%(name)s_v%(version)d,\n" % dict(name=type_str,
100 version=version))
101 out.write("""
102};
103
Andreas Wundsam53256162013-05-02 14:05:53 -0700104""" % dict(name=type_str, u_name=type_str.upper(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700105 max_val=max_val, c_name=prefix.lower()))
106
107def gen_type_maps(out):
108 """
109 Generate various type maps
110 @param out The file handle to write to
111 """
112
Rich Lanea06d0c32013-03-25 08:52:03 -0700113 # Generate maps from wire type values to object IDs
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700114 gen_type_to_object_id(out, "error_msg_type_to_id", "OF_ERROR_MSG",
115 "OF_%s_ERROR_MSG", type_maps.error_types,
116 max_type_value)
Rich Lanea06d0c32013-03-25 08:52:03 -0700117 gen_type_to_object_id(out, "action_type_to_id", "OF_ACTION",
118 "OF_ACTION_%s", type_maps.action_types,
119 max_type_value)
120 gen_type_to_object_id(out, "action_id_type_to_id", "OF_ACTION_ID",
121 "OF_ACTION_ID_%s", type_maps.action_id_types,
122 max_type_value)
123 gen_type_to_object_id(out, "instruction_type_to_id", "OF_INSTRUCTION",
Andreas Wundsam53256162013-05-02 14:05:53 -0700124 "OF_INSTRUCTION_%s", type_maps.instruction_types,
Rich Lanea06d0c32013-03-25 08:52:03 -0700125 max_type_value)
Jonathan Stoutc26cbdb2014-03-04 12:46:17 -0500126 gen_type_to_object_id(out, "instruction_id_type_to_id", "OF_INSTRUCTION_ID",
Jonathan Stout83cedcc2014-03-03 16:38:00 -0500127 "OF_INSTRUCTION_ID_%s", type_maps.instruction_id_types,
128 max_type_value)
Rich Lanea06d0c32013-03-25 08:52:03 -0700129 gen_type_to_object_id(out, "queue_prop_type_to_id", "OF_QUEUE_PROP",
130 "OF_QUEUE_PROP_%s", type_maps.queue_prop_types,
131 max_type_value)
132 gen_type_to_object_id(out, "table_feature_prop_type_to_id",
133 "OF_TABLE_FEATURE_PROP",
134 "OF_TABLE_FEATURE_PROP_%s",
135 type_maps.table_feature_prop_types,
136 max_type_value)
137 gen_type_to_object_id(out, "meter_band_type_to_id", "OF_METER_BAND",
138 "OF_METER_BAND_%s", type_maps.meter_band_types,
139 max_type_value)
140 gen_type_to_object_id(out, "hello_elem_type_to_id", "OF_HELLO_ELEM",
141 "OF_HELLO_ELEM_%s", type_maps.hello_elem_types,
142 max_type_value)
Rich Lanee3113672013-12-06 17:09:57 -0800143 gen_type_to_object_id(out, "group_mod_type_to_id", "OF_GROUP_MOD",
144 "OF_GROUP_%s", type_maps.group_mod_types,
145 max_type_value)
Rich Lanea06d0c32013-03-25 08:52:03 -0700146
147 # FIXME: Multipart re-organization
148 gen_type_to_object_id(out, "stats_request_type_to_id", "OF_STATS_REQUEST",
149 "OF_%s_STATS_REQUEST", type_maps.stats_types,
150 max_type_value)
151 gen_type_to_object_id(out, "stats_reply_type_to_id", "OF_STATS_REPLY",
152 "OF_%s_STATS_REPLY", type_maps.stats_types,
153 max_type_value)
154 gen_type_to_object_id(out, "flow_mod_type_to_id", "OF_FLOW_MOD",
155 "OF_FLOW_%s", type_maps.flow_mod_types,
156 max_type_value)
157 gen_type_to_object_id(out, "oxm_type_to_id", "OF_OXM",
158 "OF_OXM_%s", type_maps.oxm_types, max_type_value)
159 gen_type_to_object_id(out, "message_type_to_id", "OF_MESSAGE",
160 "OF_%s", type_maps.message_types, max_type_value)
161
Rich Lane713d9282013-12-30 15:21:35 -0800162 gen_type_to_object_id(out, "bsn_tlv_type_to_id", "OF_BSN_TLV",
163 "OF_BSN_TLV_%s", type_maps.bsn_tlv_types,
164 max_type_value)
165
Rich Lanea06d0c32013-03-25 08:52:03 -0700166def gen_type_to_obj_map_functions(out):
167 """
Rich Lanec0e20ff2013-12-15 23:40:31 -0800168 Generate the templated type map functions
Rich Lanea06d0c32013-03-25 08:52:03 -0700169 @param out The file handle to write to
170 """
171
172 ################################################################
173 # Generate all type-to-object-ID maps in a common way
174 ################################################################
175 map_template = """
176/**
177 * %(name)s wire type to object ID array.
178 * Treat as private; use function accessor below
179 */
180
Rich Laneb157b0f2013-03-27 13:55:28 -0700181extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];
Rich Lanea06d0c32013-03-25 08:52:03 -0700182
183#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n
184
185/**
186 * Map an %(name)s wire value to an OF object
187 * @param %(name)s The %(name)s type wire value
188 * @param version The version associated with the check
189 * @return The %(name)s OF object type
190 * @return OF_OBJECT_INVALID if type does not map to an object
Andreas Wundsam53256162013-05-02 14:05:53 -0700191 *
Rich Lanea06d0c32013-03-25 08:52:03 -0700192 */
Rich Lanec0e20ff2013-12-15 23:40:31 -0800193of_object_id_t
Andreas Wundsam53256162013-05-02 14:05:53 -0700194of_%(name)s_to_object_id(int %(name)s, of_version_t version)
Rich Lanea06d0c32013-03-25 08:52:03 -0700195{
196 if (!OF_VERSION_OKAY(version)) {
197 return OF_OBJECT_INVALID;
198 }
199 if (%(name)s < 0 || %(name)s >= OF_%(u_name)s_ITEM_COUNT) {
200 return OF_OBJECT_INVALID;
201 }
202
203 return of_%(name)s_type_to_id[version][%(name)s];
204}
205"""
206 map_with_experimenter_template = """
207/**
208 * %(name)s wire type to object ID array.
209 * Treat as private; use function accessor below
210 */
211
Rich Laneb157b0f2013-03-27 13:55:28 -0700212extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];
Rich Lanea06d0c32013-03-25 08:52:03 -0700213
214#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n
215
216/**
217 * Map an %(name)s wire value to an OF object
218 * @param %(name)s The %(name)s type wire value
219 * @param version The version associated with the check
220 * @return The %(name)s OF object type
221 * @return OF_OBJECT_INVALID if type does not map to an object
Andreas Wundsam53256162013-05-02 14:05:53 -0700222 *
Rich Lanea06d0c32013-03-25 08:52:03 -0700223 */
Rich Lanec0e20ff2013-12-15 23:40:31 -0800224of_object_id_t
Andreas Wundsam53256162013-05-02 14:05:53 -0700225of_%(name)s_to_object_id(int %(name)s, of_version_t version)
Rich Lanea06d0c32013-03-25 08:52:03 -0700226{
227 if (!OF_VERSION_OKAY(version)) {
228 return OF_OBJECT_INVALID;
229 }
230 if (%(name)s == OF_EXPERIMENTER_TYPE) {
231 return OF_%(u_name)s_EXPERIMENTER;
232 }
233 if (%(name)s < 0 || %(name)s >= OF_%(u_name)s_ITEM_COUNT) {
234 return OF_OBJECT_INVALID;
235 }
236
237 return of_%(name)s_type_to_id[version][%(name)s];
238}
239"""
Jonathan Stouta226fd72014-02-13 16:36:07 -0500240 table_features_prop_template = """
241/**
242 * %(name)s wire type to object ID array.
243 * Treat as private; use function accessor below
244 */
Rich Lanea06d0c32013-03-25 08:52:03 -0700245
Jonathan Stouta226fd72014-02-13 16:36:07 -0500246extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];
247
248#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n
249
250/**
251 * Map an %(name)s wire value to an OF object
252 * @param %(name)s The %(name)s type wire value
253 * @param version The version associated with the check
254 * @return The %(name)s OF object type
255 * @return OF_OBJECT_INVALID if type does not map to an object
256 *
257 */
258of_object_id_t
259of_%(name)s_to_object_id(int %(name)s, of_version_t version)
260{
261 if (!OF_VERSION_OKAY(version)) {
262 return OF_OBJECT_INVALID;
263 }
Jonathan Stouted300e02014-02-14 14:04:05 -0500264 if (%(name)s == 0xfffe) {
Jonathan Stouta226fd72014-02-13 16:36:07 -0500265 return OF_%(u_name)s_EXPERIMENTER;
266 }
Jonathan Stouted300e02014-02-14 14:04:05 -0500267 if (%(name)s == 0xffff) {
Jonathan Stout7a65c002014-02-13 17:27:28 -0500268 return OF_%(u_name)s_EXPERIMENTER_MISS;
269 }
Jonathan Stouta226fd72014-02-13 16:36:07 -0500270 if (%(name)s < 0 || %(name)s >= OF_%(u_name)s_ITEM_COUNT) {
271 return OF_OBJECT_INVALID;
272 }
273
274 return of_%(name)s_type_to_id[version][%(name)s];
275}
276"""
Rich Lanea06d0c32013-03-25 08:52:03 -0700277 stats_template = """
278/**
279 * %(name)s wire type to object ID array.
280 * Treat as private; use function accessor below
281 */
282
Rich Laneb157b0f2013-03-27 13:55:28 -0700283extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];
Rich Lanea06d0c32013-03-25 08:52:03 -0700284
285#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n
286
287/**
288 * Map an %(name)s wire value to an OF object
289 * @param %(name)s The %(name)s type wire value
290 * @param version The version associated with the check
291 * @return The %(name)s OF object type
292 * @return OF_OBJECT_INVALID if type does not map to an object
Andreas Wundsam53256162013-05-02 14:05:53 -0700293 *
Rich Lanea06d0c32013-03-25 08:52:03 -0700294 */
Rich Lanec0e20ff2013-12-15 23:40:31 -0800295of_object_id_t
Andreas Wundsam53256162013-05-02 14:05:53 -0700296of_%(name)s_to_object_id(int %(name)s, of_version_t version)
Rich Lanea06d0c32013-03-25 08:52:03 -0700297{
298 if (!OF_VERSION_OKAY(version)) {
299 return OF_OBJECT_INVALID;
300 }
301 if (%(name)s == OF_EXPERIMENTER_TYPE) {
302 return OF_EXPERIMENTER_%(u_name)s;
303 }
304 if (%(name)s < 0 || %(name)s >= OF_%(u_name)s_ITEM_COUNT) {
305 return OF_OBJECT_INVALID;
306 }
307
308 return of_%(name)s_type_to_id[version][%(name)s];
309}
310"""
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700311
312 error_msg_template = """
313/**
314 * %(name)s wire type to object ID array.
315 * Treat as private; use function accessor below
316 */
317
318extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];
319
320#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n
321
322/**
323 * Map an %(name)s wire value to an OF object
324 * @param %(name)s The %(name)s type wire value
325 * @param version The version associated with the check
326 * @return The %(name)s OF object type
327 * @return OF_OBJECT_INVALID if type does not map to an object
328 *
329 */
Rich Lanec0e20ff2013-12-15 23:40:31 -0800330of_object_id_t
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700331of_error_msg_to_object_id(uint16_t %(name)s, of_version_t version)
332{
333 if (!OF_VERSION_OKAY(version)) {
334 return OF_OBJECT_INVALID;
335 }
336 if (%(name)s == OF_EXPERIMENTER_TYPE) {
337 return OF_EXPERIMENTER_ERROR_MSG;
338 }
339 if (%(name)s < 0 || %(name)s >= OF_%(u_name)s_ITEM_COUNT) {
340 return OF_OBJECT_INVALID;
341 }
342
343 return of_%(name)s_type_to_id[version][%(name)s];
344}
345"""
346
Rich Lanea06d0c32013-03-25 08:52:03 -0700347 # Experimenter mapping functions
348 # Currently we support very few candidates, so we just do a
349 # list of if/elses
350 experimenter_function = """
351/**
352 * @brief Map a message known to be an exp msg to the proper object
353 *
354 * Assume that the message is a vendor/experimenter message. Determine
355 * the specific object type for the message.
356 * @param msg An OF message object (uint8_t *)
357 * @param length The number of bytes in the message (for error checking)
358 * @param version Version of message
359 * @returns object ID of specific type if recognized or OF_EXPERIMENTER if not
360 *
361 * @todo put OF_EXPERIMENTER_<name> in loci_base.h
362 */
363
Rich Lanec0e20ff2013-12-15 23:40:31 -0800364of_object_id_t
Rich Lanea06d0c32013-03-25 08:52:03 -0700365of_message_experimenter_to_object_id(of_message_t msg, of_version_t version) {
366 uint32_t experimenter_id;
367 uint32_t subtype;
368
369 /* Extract experimenter and subtype value; look for match from type maps */
370 experimenter_id = of_message_experimenter_id_get(msg);
371 subtype = of_message_experimenter_subtype_get(msg);
372
373 /* Do a simple if/else search for the ver, experimenter and subtype */
374"""
375 first = True
376 for version, experimenter_lists in type_maps.extension_message_subtype.items():
377 for exp, subtypes in experimenter_lists.items():
378 experimenter_function += """
Andreas Wundsam53256162013-05-02 14:05:53 -0700379 if ((experimenter_id == OF_EXPERIMENTER_ID_%(exp_name)s) &&
Rich Lanea06d0c32013-03-25 08:52:03 -0700380 (version == %(ver_name)s)) {
381""" % dict(exp_name=exp.upper(), ver_name=of_g.wire_ver_map[version])
382 for ext_msg, subtype in subtypes.items():
383 experimenter_function += """
384 if (subtype == %(subtype)s) {
385 return %(ext_msg)s;
386 }
387""" % dict(subtype=subtype, ext_msg=ext_msg.upper())
388 experimenter_function += """
389 }
390"""
391 experimenter_function += """
392 return OF_EXPERIMENTER;
393}
394"""
395
396 # Message need different handling
397 msg_template = """
398/**
399 * %(name)s wire type to object ID array.
400 * Treat as private; use function accessor below
401 */
402
Rich Laneb157b0f2013-03-27 13:55:28 -0700403extern const of_object_id_t *const of_%(name)s_type_to_id[OF_VERSION_ARRAY_MAX];
Rich Lanea06d0c32013-03-25 08:52:03 -0700404
405#define OF_%(u_name)s_ITEM_COUNT %(ar_len)d\n
406
407/**
408 * Extract the type info from the message and determine its object type
409 * @param msg An OF message object (uint8_t *)
410 * @param length The number of bytes in the message (for error checking)
411 * @returns object ID or OF_OBJECT_INVALID if parse error
412 */
413
Rich Lanec0e20ff2013-12-15 23:40:31 -0800414of_object_id_t
Rich Lanea06d0c32013-03-25 08:52:03 -0700415of_message_to_object_id(of_message_t msg, int length) {
416 uint8_t type;
417 of_version_t ver;
418 of_object_id_t obj_id;
419 uint16_t stats_type;
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700420 uint16_t err_type;
Rich Lanea06d0c32013-03-25 08:52:03 -0700421 uint8_t flow_mod_cmd;
Rich Lane353a79f2013-11-13 10:39:56 -0800422 uint32_t experimenter, subtype;
Rich Lanee3113672013-12-06 17:09:57 -0800423 uint16_t group_mod_cmd;
Rich Lanea06d0c32013-03-25 08:52:03 -0700424
425 if (length < OF_MESSAGE_MIN_LENGTH) {
426 return OF_OBJECT_INVALID;
427 }
428 type = of_message_type_get(msg);
429 ver = of_message_version_get(msg);
430 if (!OF_VERSION_OKAY(ver)) {
431 return OF_OBJECT_INVALID;
432 }
433
434 if (type >= OF_MESSAGE_ITEM_COUNT) {
435 return OF_OBJECT_INVALID;
436 }
437
438 obj_id = of_message_type_to_id[ver][type];
439
440 /* Remap to specific message if known */
441 if (obj_id == OF_EXPERIMENTER) {
442 if (length < OF_MESSAGE_EXPERIMENTER_MIN_LENGTH) {
443 return OF_OBJECT_INVALID;
444 }
445 return of_message_experimenter_to_object_id(msg, ver);
446 }
447
448 /* Remap to add/delete/strict version */
449 if (obj_id == OF_FLOW_MOD) {
450 if (length < OF_MESSAGE_MIN_FLOW_MOD_LENGTH(ver)) {
451 return OF_OBJECT_INVALID;
452 }
453 flow_mod_cmd = of_message_flow_mod_command_get(msg, ver);
454 obj_id = of_flow_mod_to_object_id(flow_mod_cmd, ver);
455 }
456
457 if ((obj_id == OF_STATS_REQUEST) || (obj_id == OF_STATS_REPLY)) {
458 if (length < OF_MESSAGE_MIN_STATS_LENGTH) {
459 return OF_OBJECT_INVALID;
460 }
461 stats_type = of_message_stats_type_get(msg);
Rich Lane353a79f2013-11-13 10:39:56 -0800462 if (stats_type == OF_STATS_TYPE_EXPERIMENTER) {
463 if (length < OF_MESSAGE_STATS_EXPERIMENTER_MIN_LENGTH) {
464 return OF_OBJECT_INVALID;
465 }
466 experimenter = of_message_stats_experimenter_id_get(msg);
467 subtype = of_message_stats_experimenter_subtype_get(msg);
468 if (obj_id == OF_STATS_REQUEST) {
469 obj_id = of_experimenter_stats_request_to_object_id(experimenter, subtype, ver);
470 } else {
471 obj_id = of_experimenter_stats_reply_to_object_id(experimenter, subtype, ver);
472 }
Rich Lanea06d0c32013-03-25 08:52:03 -0700473 } else {
Rich Lane353a79f2013-11-13 10:39:56 -0800474 if (obj_id == OF_STATS_REQUEST) {
475 obj_id = of_stats_request_to_object_id(stats_type, ver);
476 } else {
477 obj_id = of_stats_reply_to_object_id(stats_type, ver);
478 }
Rich Lanea06d0c32013-03-25 08:52:03 -0700479 }
480 }
481
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700482 if (obj_id == OF_ERROR_MSG) {
483 if (length < OF_MESSAGE_MIN_ERROR_LENGTH) {
484 return OF_OBJECT_INVALID;
485 }
486 err_type = of_message_error_type_get(msg);
487 obj_id = of_error_msg_to_object_id(err_type, ver);
488 }
489
Rich Lanee3113672013-12-06 17:09:57 -0800490 if (obj_id == OF_GROUP_MOD) {
491 if (length < OF_MESSAGE_MIN_GROUP_MOD_LENGTH) {
492 return OF_OBJECT_INVALID;
493 }
494 group_mod_cmd = of_message_group_mod_command_get(msg);
495 obj_id = of_group_mod_to_object_id(group_mod_cmd, ver);
496 }
497
Rich Lanea06d0c32013-03-25 08:52:03 -0700498 return obj_id;
499}
500"""
501
Rich Laned8d29c92013-09-24 13:46:42 -0700502 oxm_template = """
503/**
504 * oxm wire type to object ID array.
505 * Treat as private; use function accessor below
506 */
507
508extern const of_object_id_t *const of_oxm_type_to_id[OF_VERSION_ARRAY_MAX];
509
510#define OF_OXM_ITEM_COUNT %(ar_len)d\n
511
512/**
513 * Map an oxm wire value to an OF object
514 * @param oxm The oxm type wire value
515 * @param version The version associated with the check
516 * @return The oxm OF object type
517 * @return OF_OBJECT_INVALID if type does not map to an object
518 *
519 */
Rich Lanec0e20ff2013-12-15 23:40:31 -0800520of_object_id_t
Rich Laned8d29c92013-09-24 13:46:42 -0700521of_oxm_to_object_id(uint32_t type_len, of_version_t version)
522{
523 if (!OF_VERSION_OKAY(version)) {
524 return OF_OBJECT_INVALID;
525 }
526
527 uint16_t class = (type_len >> 16) & 0xffff;
528 uint8_t masked_type = (type_len >> 8) & 0xff;
529
530 if (class == 0x8000) {
531 if (masked_type < 0 || masked_type >= OF_OXM_ITEM_COUNT) {
532 return OF_OBJECT_INVALID;
533 }
534
535 return of_oxm_type_to_id[version][masked_type];
536 } else if (class == 0x0003) {
537 switch (masked_type) {
538 case 0x00: return OF_OXM_BSN_IN_PORTS_128;
539 case 0x01: return OF_OXM_BSN_IN_PORTS_128_MASKED;
Rich Lane61718362013-10-24 16:59:42 -0700540 case 0x02: return OF_OXM_BSN_LAG_ID;
541 case 0x03: return OF_OXM_BSN_LAG_ID_MASKED;
Rich Laneeb21c4f2013-10-28 17:34:41 -0700542 case 0x04: return OF_OXM_BSN_VRF;
543 case 0x05: return OF_OXM_BSN_VRF_MASKED;
544 case 0x06: return OF_OXM_BSN_GLOBAL_VRF_ALLOWED;
545 case 0x07: return OF_OXM_BSN_GLOBAL_VRF_ALLOWED_MASKED;
546 case 0x08: return OF_OXM_BSN_L3_INTERFACE_CLASS_ID;
547 case 0x09: return OF_OXM_BSN_L3_INTERFACE_CLASS_ID_MASKED;
548 case 0x0a: return OF_OXM_BSN_L3_SRC_CLASS_ID;
549 case 0x0b: return OF_OXM_BSN_L3_SRC_CLASS_ID_MASKED;
550 case 0x0c: return OF_OXM_BSN_L3_DST_CLASS_ID;
551 case 0x0d: return OF_OXM_BSN_L3_DST_CLASS_ID_MASKED;
Rich Laned8d29c92013-09-24 13:46:42 -0700552 default: return OF_OBJECT_INVALID;
553 }
554 } else {
555 return OF_OBJECT_INVALID;
556 }
557}
558"""
559
Rich Lanea06d0c32013-03-25 08:52:03 -0700560 # Action types array gen
561 ar_len = type_maps.type_array_len(type_maps.action_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", u_name="ACTION", ar_len=ar_len))
564
565 # Action ID types array gen
566 ar_len = type_maps.type_array_len(type_maps.action_id_types, max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700567 out.write(map_with_experimenter_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700568 dict(name="action_id", u_name="ACTION_ID", ar_len=ar_len))
569
570 # Instruction types array gen
571 ar_len = type_maps.type_array_len(type_maps.instruction_types,
572 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700573 out.write(map_with_experimenter_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700574 dict(name="instruction", u_name="INSTRUCTION", ar_len=ar_len))
575
Jonathan Stout83cedcc2014-03-03 16:38:00 -0500576 # Instruction ID types array gen
577 ar_len = type_maps.type_array_len(type_maps.instruction_id_types, max_type_value)
578 out.write(map_with_experimenter_template %
579 dict(name="instruction_id", u_name="INSTRUCTION_ID", ar_len=ar_len))
580
Rich Lanea06d0c32013-03-25 08:52:03 -0700581 # Queue prop types array gen
582 ar_len = type_maps.type_array_len(type_maps.queue_prop_types,
583 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700584 out.write(map_with_experimenter_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700585 dict(name="queue_prop", u_name="QUEUE_PROP", ar_len=ar_len))
586
587 # Table feature prop types array gen
588 ar_len = type_maps.type_array_len(type_maps.table_feature_prop_types,
589 max_type_value)
Jonathan Stout9f17b4b2014-02-14 11:56:37 -0500590 out.write(table_features_prop_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700591 dict(name="table_feature_prop", u_name="TABLE_FEATURE_PROP",
592 ar_len=ar_len))
593
594 # Meter band types array gen
595 ar_len = type_maps.type_array_len(type_maps.meter_band_types,
596 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700597 out.write(map_with_experimenter_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700598 dict(name="meter_band", u_name="METER_BAND", ar_len=ar_len))
599
600 # Hello elem types array gen
601 ar_len = type_maps.type_array_len(type_maps.hello_elem_types,
602 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700603 out.write(map_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700604 dict(name="hello_elem", u_name="HELLO_ELEM", ar_len=ar_len))
605
606 # Stats types array gen
607 ar_len = type_maps.type_array_len(type_maps.stats_types,
608 max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700609 out.write(stats_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700610 dict(name="stats_reply", u_name="STATS_REPLY", ar_len=ar_len))
Andreas Wundsam53256162013-05-02 14:05:53 -0700611 out.write(stats_template %
612 dict(name="stats_request", u_name="STATS_REQUEST",
Rich Lanea06d0c32013-03-25 08:52:03 -0700613 ar_len=ar_len))
614
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700615 ar_len = type_maps.type_array_len(type_maps.error_types,
616 max_type_value)
617 out.write(error_msg_template %
618 dict(name="error_msg", u_name="ERROR_MSG", ar_len=ar_len))
619# out.write(error_msg_function)
620
Rich Lanea06d0c32013-03-25 08:52:03 -0700621 ar_len = type_maps.type_array_len(type_maps.flow_mod_types, max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700622 out.write(map_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700623 dict(name="flow_mod", u_name="FLOW_MOD", ar_len=ar_len))
624
Rich Lanee3113672013-12-06 17:09:57 -0800625 ar_len = type_maps.type_array_len(type_maps.group_mod_types,
626 max_type_value)
627 out.write(map_template %
628 dict(name="group_mod", u_name="GROUP_MOD", ar_len=ar_len))
629
Rich Laned8d29c92013-09-24 13:46:42 -0700630 # OXM
Rich Lanea06d0c32013-03-25 08:52:03 -0700631 ar_len = type_maps.type_array_len(type_maps.oxm_types, max_type_value)
632 out.write("""
633/* NOTE: We could optimize the OXM and only generate OF 1.2 versions. */
634""")
Rich Laned8d29c92013-09-24 13:46:42 -0700635 out.write(oxm_template % dict(ar_len=ar_len))
Rich Lanea06d0c32013-03-25 08:52:03 -0700636
Rich Laned8d29c92013-09-24 13:46:42 -0700637 # Messages
Rich Lanea06d0c32013-03-25 08:52:03 -0700638 out.write(experimenter_function)
639 # Must follow stats reply/request
640 ar_len = type_maps.type_array_len(type_maps.message_types, max_type_value)
Andreas Wundsam53256162013-05-02 14:05:53 -0700641 out.write(msg_template %
Rich Lanea06d0c32013-03-25 08:52:03 -0700642 dict(name="message", u_name="MESSAGE", ar_len=ar_len))
643
Rich Lane713d9282013-12-30 15:21:35 -0800644 # BSN TLV elem types array gen
645 ar_len = type_maps.type_array_len(type_maps.bsn_tlv_types,
646 max_type_value)
647 out.write(map_template %
648 dict(name="bsn_tlv", u_name="BSN_TLV", ar_len=ar_len))
649
Rich Lanea06d0c32013-03-25 08:52:03 -0700650def gen_type_data_header(out):
651
652 out.write("""
653/****************************************************************
654 *
655 * The following declarations are for type and length calculations.
656 * Implementations may be found in of_type_maps.c
657 *
658 ****************************************************************/
659/*
660 * Special case length functions for objects with
661 */
662""")
663 for ((cls, name), prev) in of_g.special_offsets.items():
664 s_cls = cls[3:] # take off of_
665 out.write("""
666/**
667 * Special length calculation for %(cls)s->%(name)s.
Andreas Wundsam53256162013-05-02 14:05:53 -0700668 * @param obj An object of type %(cls)s to check for
Rich Lanea06d0c32013-03-25 08:52:03 -0700669 * length of %(name)s
670 * @param bytes[out] Where to store the calculated length
671 *
672 * Preceding data member is %(prev)s.
673 */
674extern int of_length_%(s_cls)s_%(name)s_get(
675 %(cls)s_t *obj, int *bytes);
676
677/**
678 * Special offset calculation for %(cls)s->%(name)s.
Andreas Wundsam53256162013-05-02 14:05:53 -0700679 * @param obj An object of type %(cls)s to check for
Rich Lanea06d0c32013-03-25 08:52:03 -0700680 * length of %(name)s
681 * @param offset[out] Where to store the calculated length
682 *
683 * Preceding data member is %(prev)s.
684 */
685extern int of_offset_%(s_cls)s_%(name)s_get(
686 %(cls)s_t *obj, int *offset);
687""" % dict(cls=cls, s_cls=s_cls, name=name, prev=prev))
688
689# NOT NEEDED YET
690# # For non-message, variable length objects, give a fun that
691# # calculates the length
692# for cls in of_g.standard_class_order:
693# s_cls = cls[3:] # take off of_
694# if !type_is_var_len(cls, version):
695# continue
696# out.write("""
697# /**
698# * Special length calculation for variable length object %(cls)s
699# * @param obj An object of type %(cls)s whose length is being calculated
700# * @param bytes[out] Where to store the calculated length
701# *
702# * The assumption is that the length member of the object is not
703# * valid and the length needs to be calculated from other information
704# * such as the parent.
705# */
706# extern int of_length_%(s_cls)s_get(
707# %(cls)s_t *obj, int *bytes);
Andreas Wundsam53256162013-05-02 14:05:53 -0700708# """ % dict(cls=cls, s_cls=s_cls))
Rich Lanea06d0c32013-03-25 08:52:03 -0700709
710 out.write("""
711/****************************************************************
712 * Wire type/length functions.
713 ****************************************************************/
714
715extern void of_object_message_wire_length_get(of_object_t *obj, int *bytes);
716extern void of_object_message_wire_length_set(of_object_t *obj, int bytes);
717
718extern void of_oxm_wire_length_get(of_object_t *obj, int *bytes);
Rich Lanea06d0c32013-03-25 08:52:03 -0700719extern void of_oxm_wire_object_id_get(of_object_t *obj, of_object_id_t *id);
Rich Lanea06d0c32013-03-25 08:52:03 -0700720
721extern void of_tlv16_wire_length_get(of_object_t *obj, int *bytes);
722extern void of_tlv16_wire_length_set(of_object_t *obj, int bytes);
723
Rich Lanea06d0c32013-03-25 08:52:03 -0700724/* Wire length is uint16 at front of structure */
725extern void of_u16_len_wire_length_get(of_object_t *obj, int *bytes);
726extern void of_u16_len_wire_length_set(of_object_t *obj, int bytes);
727
728extern void of_action_wire_object_id_get(of_object_t *obj, of_object_id_t *id);
729extern void of_action_id_wire_object_id_get(of_object_t *obj, of_object_id_t *id);
Andreas Wundsam53256162013-05-02 14:05:53 -0700730extern void of_instruction_wire_object_id_get(of_object_t *obj,
Rich Lanea06d0c32013-03-25 08:52:03 -0700731 of_object_id_t *id);
Jonathan Stout83cedcc2014-03-03 16:38:00 -0500732extern void of_instruction_id_wire_object_id_get(of_object_t *obj,
733 of_object_id_t *id);
Andreas Wundsam53256162013-05-02 14:05:53 -0700734extern void of_queue_prop_wire_object_id_get(of_object_t *obj,
Rich Lanea06d0c32013-03-25 08:52:03 -0700735 of_object_id_t *id);
Andreas Wundsam53256162013-05-02 14:05:53 -0700736extern void of_table_feature_prop_wire_object_id_get(of_object_t *obj,
Rich Lanea06d0c32013-03-25 08:52:03 -0700737 of_object_id_t *id);
Andreas Wundsam53256162013-05-02 14:05:53 -0700738extern void of_meter_band_wire_object_id_get(of_object_t *obj,
Rich Lanea06d0c32013-03-25 08:52:03 -0700739 of_object_id_t *id);
Andreas Wundsam53256162013-05-02 14:05:53 -0700740extern void of_hello_elem_wire_object_id_get(of_object_t *obj,
Rich Lanea06d0c32013-03-25 08:52:03 -0700741 of_object_id_t *id);
Rich Lane713d9282013-12-30 15:21:35 -0800742extern void of_bsn_tlv_wire_object_id_get(of_object_t *obj,
743 of_object_id_t *id);
Rich Lanea06d0c32013-03-25 08:52:03 -0700744
Rich Lane47085722013-07-12 16:27:04 -0700745#define OF_OXM_LENGTH_GET(hdr) (((hdr) & 0xff) + 4)
Rich Lanea06d0c32013-03-25 08:52:03 -0700746#define OF_OXM_LENGTH_SET(hdr, val) \\
Rich Lane47085722013-07-12 16:27:04 -0700747 (hdr) = ((hdr) & 0xffffff00) + (((val) - 4) & 0xff)
Rich Lanea06d0c32013-03-25 08:52:03 -0700748
749extern void of_packet_queue_wire_length_get(of_object_t *obj, int *bytes);
750extern void of_packet_queue_wire_length_set(of_object_t *obj, int bytes);
751
752extern void of_list_meter_band_stats_wire_length_get(of_object_t *obj,
753 int *bytes);
754extern void of_meter_stats_wire_length_get(of_object_t *obj, int *bytes);
755extern void of_meter_stats_wire_length_set(of_object_t *obj, int bytes);
756extern int of_extension_object_wire_push(of_object_t *obj);
757
758""")
759
760
761def gen_length_array(out):
762 """
763 Generate an array giving the lengths of all objects/versions
764 @param out The file handle to which to write
765 """
766 out.write("""
767/**
768 * An array with the number of bytes in the fixed length part
769 * of each OF object
770 */
771""")
772
773 for version in of_g.of_version_range:
774 out.write("""
Rich Laneb157b0f2013-03-27 13:55:28 -0700775static const int\nof_object_fixed_len_v%d[OF_OBJECT_COUNT] = {
Rich Lanea06d0c32013-03-25 08:52:03 -0700776 -1, /* of_object is not instantiable */
777""" % version)
778 for i, cls in enumerate(of_g.all_class_order):
779 comma = ","
780 if i == len(of_g.all_class_order) - 1:
781 comma = ""
782 val = "-1" + comma
783 if (cls, version) in of_g.base_length:
784 val = str(of_g.base_length[(cls, version)]) + comma
785 out.write(" %-5s /* %d: %s */\n" % (val, i + 1, cls))
786 out.write("};\n")
787
788 out.write("""
789/**
790 * Unified map of fixed length part of each object
791 */
Rich Laneb157b0f2013-03-27 13:55:28 -0700792const int *const of_object_fixed_len[OF_VERSION_ARRAY_MAX] = {
Rich Lanea06d0c32013-03-25 08:52:03 -0700793 NULL,
794""")
795 for version in of_g.of_version_range:
796 out.write(" of_object_fixed_len_v%d,\n" % version)
797 out.write("""
798};
799""")
800
Andreas Wundsam53256162013-05-02 14:05:53 -0700801
Rich Lanef70be942013-07-18 13:33:14 -0700802def gen_extra_length_array(out):
803 """
804 Generate an array giving the extra lengths of all objects/versions
805 @param out The file handle to which to write
806 """
807 out.write("""
808/**
809 * An array with the number of bytes in the extra length part
810 * of each OF object
811 */
812""")
813
814 for version in of_g.of_version_range:
815 out.write("""
816static const int\nof_object_extra_len_v%d[OF_OBJECT_COUNT] = {
817 -1, /* of_object is not instantiable */
818""" % version)
819 for i, cls in enumerate(of_g.all_class_order):
820 comma = ","
821 if i == len(of_g.all_class_order) - 1:
822 comma = ""
823 val = "-1" + comma
824 if (cls, version) in of_g.base_length:
825 val = str(of_g.extra_length.get((cls, version), 0)) + comma
826 out.write(" %-5s /* %d: %s */\n" % (val, i + 1, cls))
827 out.write("};\n")
828
829 out.write("""
830/**
831 * Unified map of extra length part of each object
832 */
833const int *const of_object_extra_len[OF_VERSION_ARRAY_MAX] = {
834 NULL,
835""")
836 for version in of_g.of_version_range:
837 out.write(" of_object_extra_len_v%d,\n" % version)
838 out.write("""
839};
840""")