blob: b64f1b5a4086b92f4f158f5e0d1b1ab7611863b8 [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# Miscellaneous type information
30#
31# Define the map between sub-class types and wire values. In each
32# case, an array indexed by wire version gives a hash from identifier
33# to wire value.
34#
35
36import of_g
37import sys
38from generic_utils import *
Rich Lanea06d0c32013-03-25 08:52:03 -070039import loxi_utils.loxi_utils as loxi_utils
40
41invalid_type = "invalid_type"
42invalid_value = "0xeeee" # Note, as a string
43
44################################################################
45#
46# Define type data for inheritance classes:
47# instructions, actions, queue properties and OXM
48#
49# Messages are not in this group; they're treated specially for now
50#
51# These are indexed by wire protocol number
52#
53################################################################
54
55instruction_types = {
Rich Lanea06d0c32013-03-25 08:52:03 -070056 of_g.VERSION_1_0:dict(),
Rich Lane4db4d042013-05-13 18:13:48 -070057 of_g.VERSION_1_1:dict(),
58 of_g.VERSION_1_2:dict(),
59 of_g.VERSION_1_3:dict()
Rich Lanea06d0c32013-03-25 08:52:03 -070060 }
61
Rich Lane4db4d042013-05-13 18:13:48 -070062# HACK shared between actions and action_ids
63of_1_3_action_types = dict()
Rich Lanea06d0c32013-03-25 08:52:03 -070064
Rich Lanea06d0c32013-03-25 08:52:03 -070065action_types = {
Rich Lane4db4d042013-05-13 18:13:48 -070066 of_g.VERSION_1_0:dict(),
67 of_g.VERSION_1_1:dict(),
68 of_g.VERSION_1_2:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -070069 of_g.VERSION_1_3:of_1_3_action_types
Rich Lanea06d0c32013-03-25 08:52:03 -070070 }
71
72action_id_types = {
Rich Lanea06d0c32013-03-25 08:52:03 -070073 of_g.VERSION_1_0:dict(),
74 of_g.VERSION_1_1:dict(),
75 of_g.VERSION_1_2:dict(),
76 of_g.VERSION_1_3:of_1_3_action_types
77 }
78
79queue_prop_types = {
Rich Lane4db4d042013-05-13 18:13:48 -070080 of_g.VERSION_1_0:dict(),
81 of_g.VERSION_1_1:dict(),
82 of_g.VERSION_1_2:dict(),
83 of_g.VERSION_1_3:dict()
Rich Lanea06d0c32013-03-25 08:52:03 -070084 }
85
Dan Talaycoc0e802e2013-05-18 23:52:39 -070086bsn_vport_types = {
87 # version 1.0
88 of_g.VERSION_1_0:dict(
89 q_in_q = 0,
90 ),
91 # version 1.1
92 of_g.VERSION_1_1:dict(
93 q_in_q = 0,
94 ),
95 # version 1.2
96 of_g.VERSION_1_2:dict(
97 q_in_q = 0,
98 ),
99 # version 1.3
100 of_g.VERSION_1_3:dict(
101 q_in_q = 0,
102 )
103 }
104
Rich Lanea06d0c32013-03-25 08:52:03 -0700105oxm_types = {
Rich Lanea06d0c32013-03-25 08:52:03 -0700106 of_g.VERSION_1_0:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700107 of_g.VERSION_1_1:dict(),
Rich Lane4db4d042013-05-13 18:13:48 -0700108 of_g.VERSION_1_2:dict(),
109 of_g.VERSION_1_3:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700110 }
111
112hello_elem_types = {
Rich Lanea06d0c32013-03-25 08:52:03 -0700113 of_g.VERSION_1_0:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700114 of_g.VERSION_1_1:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700115 of_g.VERSION_1_2:dict(),
Rich Lane4db4d042013-05-13 18:13:48 -0700116 of_g.VERSION_1_3:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700117 }
118
119table_feature_prop_types = {
Rich Lanea06d0c32013-03-25 08:52:03 -0700120 of_g.VERSION_1_0:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700121 of_g.VERSION_1_1:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700122 of_g.VERSION_1_2:dict(),
Rich Lane4db4d042013-05-13 18:13:48 -0700123 of_g.VERSION_1_3:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700124 }
125
126meter_band_types = {
Rich Lanea06d0c32013-03-25 08:52:03 -0700127 of_g.VERSION_1_0:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700128 of_g.VERSION_1_1:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700129 of_g.VERSION_1_2:dict(),
Rich Lane4db4d042013-05-13 18:13:48 -0700130 of_g.VERSION_1_3:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700131 }
132
133# All inheritance data for non-messages
134inheritance_data = dict(
135 of_instruction = instruction_types,
136 of_action = action_types,
137 of_action_id = action_id_types,
138 of_oxm = oxm_types,
139 of_queue_prop = queue_prop_types,
140 of_hello_elem = hello_elem_types,
141 of_table_feature_prop = table_feature_prop_types,
Dan Talaycoc0e802e2013-05-18 23:52:39 -0700142 of_meter_band = meter_band_types,
143 # BSN specific inheritance extensions
144 of_bsn_vport = bsn_vport_types
Rich Lanea06d0c32013-03-25 08:52:03 -0700145 )
146
Rich Lanea06d0c32013-03-25 08:52:03 -0700147def class_is_virtual(cls):
148 """
149 Returns True if cls is a virtual class
150 """
151 if cls in inheritance_map:
152 return True
153 if cls.find("header") > 0:
154 return True
155 if loxi_utils.class_is_list(cls):
156 return True
Rich Lane488b3c52013-06-21 18:11:02 -0700157 # TODO get this from the input file when we have virtual class syntax
158 if cls in ["of_flow_mod", "of_stats_request", "of_stats_reply", "of_bsn_header", "of_nicira_header", "of_action_bsn", "of_action_nicira", "of_action_id_bsn", "of_action_id_nicira"]:
159 return True
Rich Lanea06d0c32013-03-25 08:52:03 -0700160 return False
161
162################################################################
163#
164# These are message types
165#
166################################################################
167
Rich Lanedf847e32013-05-29 16:57:30 -0700168# The hardcoded message types are for inheritance parents
Rich Lanea06d0c32013-03-25 08:52:03 -0700169message_types = {
170 # version 1.0
171 of_g.VERSION_1_0:dict(
Rich Lanedf847e32013-05-29 16:57:30 -0700172 experimenter = 4,
Rich Lanea06d0c32013-03-25 08:52:03 -0700173 flow_mod = 14,
Rich Lanea06d0c32013-03-25 08:52:03 -0700174 stats_request = 16,
175 stats_reply = 17,
Rich Lanea06d0c32013-03-25 08:52:03 -0700176 ),
177
178 # version 1.1
179 of_g.VERSION_1_1:dict(
Rich Lanedf847e32013-05-29 16:57:30 -0700180 experimenter = 4,
Rich Lanea06d0c32013-03-25 08:52:03 -0700181 flow_mod = 14,
Rich Lanea06d0c32013-03-25 08:52:03 -0700182 stats_request = 18,
183 stats_reply = 19,
Rich Lanea06d0c32013-03-25 08:52:03 -0700184 ),
185
186 # version 1.2
187 of_g.VERSION_1_2:dict(
Rich Lanedf847e32013-05-29 16:57:30 -0700188 experimenter = 4,
Rich Lanea06d0c32013-03-25 08:52:03 -0700189 flow_mod = 14,
Rich Lanea06d0c32013-03-25 08:52:03 -0700190 stats_request = 18,
191 stats_reply = 19,
Rich Lanea06d0c32013-03-25 08:52:03 -0700192 ),
193
194 # version 1.3
195 of_g.VERSION_1_3:dict(
Rich Lanedf847e32013-05-29 16:57:30 -0700196 experimenter = 4,
Rich Lanea06d0c32013-03-25 08:52:03 -0700197 flow_mod = 14,
Rich Lanea06d0c32013-03-25 08:52:03 -0700198 stats_request = 18, # FIXME Multipart
199 stats_reply = 19,
Rich Lanea06d0c32013-03-25 08:52:03 -0700200 )
201 }
202
203################################################################
204#
205# These are other objects that have a notion of type but are
206# not (yet) promoted to objects with inheritance
207#
208################################################################
209
210stats_types = {
211 # version 1.0
212 of_g.VERSION_1_0:dict(
213 desc = 0,
214 flow = 1,
215 aggregate = 2,
216 table = 3,
217 port = 4,
218 queue = 5,
219 experimenter = 0xffff
220 ),
221
222 # version 1.1
223 of_g.VERSION_1_1:dict(
224 desc = 0,
225 flow = 1,
226 aggregate = 2,
227 table = 3,
228 port = 4,
229 queue = 5,
230 group = 6,
231 group_desc = 7,
232 experimenter = 0xffff
233 ),
234
235 # version 1.2
236 of_g.VERSION_1_2:dict(
237 desc = 0,
238 flow = 1,
239 aggregate = 2,
240 table = 3,
241 port = 4,
242 queue = 5,
243 group = 6,
244 group_desc = 7,
245 group_features = 8,
246 experimenter = 0xffff
247 ),
248
249 # version 1.3
250 of_g.VERSION_1_3:dict(
251 desc = 0,
252 flow = 1,
253 aggregate = 2,
254 table = 3,
255 port = 4,
256 queue = 5,
257 group = 6,
258 group_desc = 7,
259 group_features = 8,
260 meter = 9,
261 meter_config = 10,
262 meter_features = 11,
263 table_features = 12,
264 port_desc = 13,
265 experimenter = 0xffff
266 )
267 }
268
269common_flow_mod_types = dict(
270 add = 0,
271 modify = 1,
272 modify_strict = 2,
273 delete = 3,
274 delete_strict = 4
275 )
276
277flow_mod_types = {
278 # version 1.0
279 of_g.VERSION_1_0:common_flow_mod_types,
280 of_g.VERSION_1_1:common_flow_mod_types,
281 of_g.VERSION_1_2:common_flow_mod_types,
282 of_g.VERSION_1_3:common_flow_mod_types
283 }
284
285# These do not translate to objects (yet)
286error_types = {
287 # version 1.0
288 of_g.VERSION_1_0:dict(
289 hello_failed = 0,
290 bad_request = 1,
291 bad_action = 2,
292 flow_mod_failed = 3,
293 port_mod_failed = 4,
294 queue_op_failed = 5
295 ),
296
297 # version 1.1
298 of_g.VERSION_1_1:dict(
299 hello_failed = 0,
300 bad_request = 1,
301 bad_action = 2,
302 bad_instruction = 3,
303 bad_match = 4,
304 flow_mod_failed = 5,
305 group_mod_failed = 6,
306 port_mod_failed = 7,
307 table_mod_failed = 8,
308 queue_op_failed = 9,
309 switch_config_failed = 10
310 ),
311
312 # version 1.2
313 of_g.VERSION_1_2:dict(
314 hello_failed = 0,
315 bad_request = 1,
316 bad_action = 2,
317 bad_instruction = 3,
318 bad_match = 4,
319 flow_mod_failed = 5,
320 group_mod_failed = 6,
321 port_mod_failed = 7,
322 table_mod_failed = 8,
323 queue_op_failed = 9,
324 switch_config_failed = 10,
325 role_request_failed = 11,
326 experimenter = 0xffff
327 ),
328
329 # version 1.3
330 of_g.VERSION_1_3:dict(
331 hello_failed = 0,
332 bad_request = 1,
333 bad_action = 2,
334 bad_instruction = 3,
335 bad_match = 4,
336 flow_mod_failed = 5,
337 group_mod_failed = 6,
338 port_mod_failed = 7,
339 table_mod_failed = 8,
340 queue_op_failed = 9,
341 switch_config_failed = 10,
342 role_request_failed = 11,
343 meter_mod_failed = 12,
344 table_features_failed= 13,
345 experimenter = 0xffff
346 )
347 }
348
349##
350# These are the objects whose length is specified by an external
351# reference, specifically another data member in the class.
Andreas Wundsam53256162013-05-02 14:05:53 -0700352#
Rich Lanea06d0c32013-03-25 08:52:03 -0700353#external_length_spec = {
354# ("of_packet_out", "actions", OF_VERSION_1_0) : "actions_len",
355# ("of_packet_out", "actions", OF_VERSION_1_1) : "actions_len",
356# ("of_packet_out", "actions", OF_VERSION_1_2) : "actions_len",
357# ("of_packet_out", "actions", OF_VERSION_1_3) : "actions_len"
358#}
359
360
361################################################################
362#
Andreas Wundsam53256162013-05-02 14:05:53 -0700363# type_val is the primary data structure that maps an
Rich Lanea06d0c32013-03-25 08:52:03 -0700364# (class_name, version) pair to the wire data type value
365#
366################################################################
367
368type_val = dict()
Rich Lane6bb28dd2013-05-13 15:19:14 -0700369inheritance_map = dict()
Rich Lanea06d0c32013-03-25 08:52:03 -0700370
Rich Lane6bb28dd2013-05-13 15:19:14 -0700371def generate_maps():
372 for parent, versioned in inheritance_data.items():
373 inheritance_map[parent] = set()
374 for ver, subclasses in versioned.items():
375 for subcls in subclasses:
376 inheritance_map[parent].add(subcls)
Rich Lanea06d0c32013-03-25 08:52:03 -0700377
Rich Lane6bb28dd2013-05-13 15:19:14 -0700378 for version, classes in message_types.items():
379 for cls in classes:
380 name = "of_" + cls
381 type_val[(name, version)] = classes[cls]
Rich Lanea06d0c32013-03-25 08:52:03 -0700382
Rich Lane6bb28dd2013-05-13 15:19:14 -0700383 for parent, versioned in inheritance_data.items():
384 for version, subclasses in versioned.items():
385 for subcls, value in subclasses.items():
386 name = parent + "_" + subcls
387 type_val[(name, version)] = value
388
389 # Special case OF-1.2 match type
Rich Lanea72c98e2013-07-12 16:40:06 -0700390 type_val[("of_match_v3", of_g.VERSION_1_2)] = 1
391 type_val[("of_match_v3", of_g.VERSION_1_3)] = 1
Rich Lanea06d0c32013-03-25 08:52:03 -0700392
393# Utility function
394def dict_to_array(d, m_val, def_val=-1):
395 """
396 Given a dictionary, d, with each value a small integer,
397 produce an array indexed by the integer whose value is the key.
398 @param d The dictionary
399 @param m_val Ignore values greater than m_val
400 @param def_val The default value (for indices not in range of d)
401 """
402
403 # Get the max value in range for hash
404 max_val = 0
405 for key in d:
406 if (d[key] > max_val) and (d[key] < m_val):
407 max_val = d[key]
408 ar = []
409 for x in range(0, max_val + 1):
410 ar.append(def_val)
411 for key in d:
412 if (d[key] < m_val):
413 ar[d[key]] = key
414 return ar
415
416def type_array_len(version_indexed, max_val):
417 """
418 Given versioned information about a type, calculate how long
419 the unified array should be.
420
Andreas Wundsam53256162013-05-02 14:05:53 -0700421 @param version_indexed A dict indexed by version. Each value is a
Rich Lanea06d0c32013-03-25 08:52:03 -0700422 dict indexed by a name and whose value is an integer
423 @param max_val Ignore values greater than this for length calcs
424 """
425 # First, find the max length of all arrays
426 arr_len = 0
427 for version, val_dict in version_indexed.items():
428 ar = dict_to_array(val_dict, max_val, invalid_type)
429 if arr_len < len(ar):
430 arr_len = len(ar)
431 return arr_len
432
433# FIXME: Need to move update for multipart messages
434
435stats_reply_list = [
436 "of_aggregate_stats_reply",
437 "of_desc_stats_reply",
438 "of_experimenter_stats_reply",
439 "of_flow_stats_reply",
440 "of_group_stats_reply",
441 "of_group_desc_stats_reply",
442 "of_group_features_stats_reply",
443 "of_meter_stats_reply",
444 "of_meter_config_stats_reply",
445 "of_meter_features_stats_reply",
446 "of_port_stats_reply",
447 "of_port_desc_stats_reply",
448 "of_queue_stats_reply",
449 "of_table_stats_reply",
450 "of_table_features_stats_reply"
451]
452
453stats_request_list = [
454 "of_aggregate_stats_request",
455 "of_desc_stats_request",
456 "of_experimenter_stats_request",
457 "of_flow_stats_request",
458 "of_group_stats_request",
459 "of_group_desc_stats_request",
460 "of_group_features_stats_request",
461 "of_meter_stats_request",
462 "of_meter_config_stats_request",
463 "of_meter_features_stats_request",
464 "of_port_stats_request",
465 "of_port_desc_stats_request",
466 "of_queue_stats_request",
467 "of_table_stats_request",
468 "of_table_features_stats_request"
469]
470
471flow_mod_list = [
472 "of_flow_add",
473 "of_flow_modify",
474 "of_flow_modify_strict",
475 "of_flow_delete",
476 "of_flow_delete_strict"
477]
478
479def sub_class_map(base_type, version):
480 """
481 Returns an iterable object giving the instance nameys and subclass types
482 for the base_type, version values
483 """
484 rv = []
485 if base_type not in inheritance_map:
486 return rv
487
488 for instance in inheritance_map[base_type]:
489 subcls = loxi_utils.instance_to_class(instance, base_type)
490 if not loxi_utils.class_in_version(subcls, version):
491 continue
492 rv.append((instance, subcls))
493
494 return rv
495
496################################################################
497#
498# Extension related data and functions
499#
500################################################################
501
502# Per OF Version, per experimenter, map exp msg type (subtype) to object IDs
503# @fixme Generate defines for OF_<exp>_SUBTYPE_<msg> for the values below?
504extension_message_subtype = {
505 # version 1.0
506 of_g.VERSION_1_0:dict( # Version 1.0 extensions
507 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700508 },
509 nicira = { # Nicira extensions, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700510 },
511 ),
512 of_g.VERSION_1_1:dict( # Version 1.0 extensions
513 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700514 },
515 ),
516 of_g.VERSION_1_2:dict( # Version 1.0 extensions
517 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700518 },
519 ),
520 of_g.VERSION_1_3:dict( # Version 1.0 extensions
521 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700522 },
523 ),
524}
525
526# Set to empty dict if no extension actions defined
527# Per OF Version, per experimenter, map actions to subtype
528extension_action_subtype = {
529 # version 1.0
530 of_g.VERSION_1_0:dict( # Version 1.0 extensions
531 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700532 },
533 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700534 }
535 ),
536 of_g.VERSION_1_1:dict( # Version 1.0 extensions
537 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700538 },
539 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700540 }
541 ),
542 of_g.VERSION_1_2:dict( # Version 1.0 extensions
543 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700544 },
545 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700546 }
547 ),
548 of_g.VERSION_1_3:dict( # Version 1.0 extensions
549 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700550 },
551 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700552 }
553 ),
554}
555
556# Set to empty dict if no extension actions defined
557# Per OF Version, per experimenter, map actions to subtype
558extension_action_id_subtype = {
559 # version 1.0
560 of_g.VERSION_1_0:dict(),
561 of_g.VERSION_1_1:dict(),
562 of_g.VERSION_1_2:dict(),
563 of_g.VERSION_1_3:dict( # Version 1.3 extensions
564 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700565 },
566 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700567 }
568 ),
569}
570
571# Set to empty dict if no extension instructions defined
572extension_instruction_subtype = {}
573
574# Set to empty dict if no extension instructions defined
575extension_queue_prop_subtype = {}
576
577# Set to empty dict if no extension instructions defined
578extension_table_feature_prop_subtype = {}
579
580extension_objects = [
581 extension_message_subtype,
582 extension_action_subtype,
583 extension_action_id_subtype,
584 extension_instruction_subtype,
585 extension_queue_prop_subtype,
586 extension_table_feature_prop_subtype
587]
588
589################################################################
590# These are extension type generic (for messages, actions...)
591################################################################
592
593def extension_to_experimenter_name(cls):
594 """
595 Return the name of the experimenter if class is an
596 extension, else None
597
598 This is brute force; we search all extension data for a match
599 """
Andreas Wundsam53256162013-05-02 14:05:53 -0700600
Rich Lanea06d0c32013-03-25 08:52:03 -0700601 for ext_obj in extension_objects:
602 for version, exp_list in ext_obj.items():
603 for exp_name, classes in exp_list.items():
604 if cls in classes:
605 return exp_name
606 return None
607
608def extension_to_experimenter_id(cls):
609 """
610 Return the ID of the experimenter if class is an
611 extension, else None
612 """
613 exp_name = extension_to_experimenter_name(cls)
614 if exp_name:
615 return of_g.experimenter_name_to_id[exp_name]
616 return None
617
618def extension_to_experimenter_macro_name(cls):
619 """
620 Return the "macro name" of the ID of the experimenter if class is an
621 extension, else None
622 """
623 exp_name = extension_to_experimenter_name(cls)
624 if exp_name:
625 return "OF_EXPERIMENTER_ID_" + exp_name.upper()
626 return None
627
628def extension_to_subtype(cls, version):
629 """
630 Generic across all extension objects, return subtype identifier
631 """
632 for ext_obj in extension_objects:
633 for version, exp_list in ext_obj.items():
634 for exp_name, classes in exp_list.items():
635 if cls in classes:
636 return classes[cls]
637
638def class_is_extension(cls, version):
639 """
640 Return True if class, version is recognized as an extension
641 of any type (message, action....)
642
643 Accepts of_g.OF_VERSION_ANY
644 """
645
646 for ext_obj in extension_objects:
647 if cls_is_ext_obj(cls, version, ext_obj):
648 return True
649
650 return False
651
652# Internal
653def cls_is_ext_obj(cls, version, ext_obj):
654 """
655 @brief Return True if cls in an extension of type ext_obj
656 @param cls The class to check
657 @param version The version to check
658 @param ext_obj The extension object dictionary (messages, actions...)
659
660 Accepts of_g.VERSION_ANY
661 """
662
663 # Call with each version if "any" is passed
664 if version == of_g.VERSION_ANY:
665 for v in of_g.of_version_range:
666 if cls_is_ext_obj(cls, v, ext_obj):
667 return True
668 else: # Version specified
669 if version in ext_obj:
670 for exp, subtype_vals in ext_obj[version].items():
671 if cls in subtype_vals:
672 return True
673
674 return False
Andreas Wundsam53256162013-05-02 14:05:53 -0700675
Rich Lanea06d0c32013-03-25 08:52:03 -0700676################################################################
677# These are extension message specific
678################################################################
679
680def message_is_extension(cls, version):
681 """
682 Return True if cls, version is recognized as an extension
683 This is brute force, searching records for a match
684 """
685 return cls_is_ext_obj(cls, version, extension_message_subtype)
686
687def extension_message_to_subtype(cls, version):
688 """
689 Return the subtype of the experimenter message if the class is an
690 extension, else None
691 """
692 if version in extension_message_subtype:
693 for exp, classes in extension_message_subtype[version].items():
694 for ext_class, subtype in classes.items():
695 if cls == ext_class:
696 return subtype
697 return None
698
699################################################################
700# These are extension action specific
701################################################################
702
703def action_is_extension(cls, version):
704 """
705 Return True if cls, version is recognized as an action extension
706 This is brute force, searching records for a match
707 """
708 return cls_is_ext_obj(cls, version, extension_action_subtype)
709
710def extension_action_to_subtype(cls, version):
711 """
712 Return the ID of the action subtype (for its experimenteer)
713 if class is an action extension, else None
714 """
715 if version in extension_action_subtype:
716 for exp, classes in extension_action_subtype[version].items():
717 if cls in classes:
718 return classes[cls]
719
720 return None
721
722################################################################
723# These are extension action specific
724################################################################
725
726def action_id_is_extension(cls, version):
727 """
728 Return True if cls, version is recognized as an action ID extension
729 This is brute force, searching records for a match
730 """
731 if version not in [of_g.VERSION_1_3]: # Action IDs only 1.3
732 return False
733 return cls_is_ext_obj(cls, version, extension_action_id_subtype)
734
735def extension_action_id_to_subtype(cls, version):
736 """
737 Return the ID of the action ID subtype (for its experimenteer)
738 if class is an action ID extension, else None
739 """
740 if version in extension_action_id_subtype:
741 for exp, classes in extension_action_id_subtype[version].items():
742 if cls in classes:
743 return classes[cls]
744
745 return None
746
747################################################################
748# These are extension instruction specific
749################################################################
750
751def instruction_is_extension(cls, version):
752 """
753 Return True if cls, version is recognized as an instruction extension
754 This is brute force, searching records for a match
755 """
756 return cls_is_ext_obj(cls, version, extension_instruction_subtype)
757
758################################################################
759# These are extension queue_prop specific
760################################################################
761
762def queue_prop_is_extension(cls, version):
763 """
764 Return True if cls, version is recognized as an instruction extension
765 This is brute force, searching records for a match
766 """
767 return cls_is_ext_obj(cls, version, extension_queue_prop_subtype)
768
769################################################################
770# These are extension table_feature_prop specific
771################################################################
772
773def table_feature_prop_is_extension(cls, version):
774 """
775 Return True if cls, version is recognized as an instruction extension
776 This is brute force, searching records for a match
777 """
778 return cls_is_ext_obj(cls, version,
779 extension_table_feature_prop_subtype)