blob: a3394b2dc2df58d6db00aa377ce3d606557dbfc6 [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
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700158 if cls in ["of_flow_mod", "of_stats_request", "of_stats_reply", "of_error_msg", "of_bsn_header", "of_nicira_header", "of_action_bsn", "of_action_nicira", "of_action_id_bsn", "of_action_id_nicira"]:
Rich Lane488b3c52013-06-21 18:11:02 -0700159 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(
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700172 error_msg = 1,
Rich Lanedf847e32013-05-29 16:57:30 -0700173 experimenter = 4,
Rich Lanea06d0c32013-03-25 08:52:03 -0700174 flow_mod = 14,
Rich Lanea06d0c32013-03-25 08:52:03 -0700175 stats_request = 16,
176 stats_reply = 17,
Rich Lanea06d0c32013-03-25 08:52:03 -0700177 ),
178
179 # version 1.1
180 of_g.VERSION_1_1:dict(
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700181 error_msg = 1,
Rich Lanedf847e32013-05-29 16:57:30 -0700182 experimenter = 4,
Rich Lanea06d0c32013-03-25 08:52:03 -0700183 flow_mod = 14,
Rich Lanea06d0c32013-03-25 08:52:03 -0700184 stats_request = 18,
185 stats_reply = 19,
Rich Lanea06d0c32013-03-25 08:52:03 -0700186 ),
187
188 # version 1.2
189 of_g.VERSION_1_2:dict(
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700190 error_msg = 1,
Rich Lanedf847e32013-05-29 16:57:30 -0700191 experimenter = 4,
Rich Lanea06d0c32013-03-25 08:52:03 -0700192 flow_mod = 14,
Rich Lanea06d0c32013-03-25 08:52:03 -0700193 stats_request = 18,
194 stats_reply = 19,
Rich Lanea06d0c32013-03-25 08:52:03 -0700195 ),
196
197 # version 1.3
198 of_g.VERSION_1_3:dict(
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700199 error_msg = 1,
Rich Lanedf847e32013-05-29 16:57:30 -0700200 experimenter = 4,
Rich Lanea06d0c32013-03-25 08:52:03 -0700201 flow_mod = 14,
Rich Lanea06d0c32013-03-25 08:52:03 -0700202 stats_request = 18, # FIXME Multipart
203 stats_reply = 19,
Rich Lanea06d0c32013-03-25 08:52:03 -0700204 )
205 }
206
207################################################################
208#
209# These are other objects that have a notion of type but are
210# not (yet) promoted to objects with inheritance
211#
212################################################################
213
214stats_types = {
215 # version 1.0
216 of_g.VERSION_1_0:dict(
217 desc = 0,
218 flow = 1,
219 aggregate = 2,
220 table = 3,
221 port = 4,
222 queue = 5,
223 experimenter = 0xffff
224 ),
225
226 # version 1.1
227 of_g.VERSION_1_1:dict(
228 desc = 0,
229 flow = 1,
230 aggregate = 2,
231 table = 3,
232 port = 4,
233 queue = 5,
234 group = 6,
235 group_desc = 7,
236 experimenter = 0xffff
237 ),
238
239 # version 1.2
240 of_g.VERSION_1_2:dict(
241 desc = 0,
242 flow = 1,
243 aggregate = 2,
244 table = 3,
245 port = 4,
246 queue = 5,
247 group = 6,
248 group_desc = 7,
249 group_features = 8,
250 experimenter = 0xffff
251 ),
252
253 # version 1.3
254 of_g.VERSION_1_3:dict(
255 desc = 0,
256 flow = 1,
257 aggregate = 2,
258 table = 3,
259 port = 4,
260 queue = 5,
261 group = 6,
262 group_desc = 7,
263 group_features = 8,
264 meter = 9,
265 meter_config = 10,
266 meter_features = 11,
267 table_features = 12,
268 port_desc = 13,
269 experimenter = 0xffff
270 )
271 }
272
273common_flow_mod_types = dict(
274 add = 0,
275 modify = 1,
276 modify_strict = 2,
277 delete = 3,
278 delete_strict = 4
279 )
280
281flow_mod_types = {
282 # version 1.0
283 of_g.VERSION_1_0:common_flow_mod_types,
284 of_g.VERSION_1_1:common_flow_mod_types,
285 of_g.VERSION_1_2:common_flow_mod_types,
286 of_g.VERSION_1_3:common_flow_mod_types
287 }
288
289# These do not translate to objects (yet)
290error_types = {
291 # version 1.0
292 of_g.VERSION_1_0:dict(
293 hello_failed = 0,
294 bad_request = 1,
295 bad_action = 2,
296 flow_mod_failed = 3,
297 port_mod_failed = 4,
298 queue_op_failed = 5
299 ),
300
301 # version 1.1
302 of_g.VERSION_1_1:dict(
303 hello_failed = 0,
304 bad_request = 1,
305 bad_action = 2,
306 bad_instruction = 3,
307 bad_match = 4,
308 flow_mod_failed = 5,
309 group_mod_failed = 6,
310 port_mod_failed = 7,
311 table_mod_failed = 8,
312 queue_op_failed = 9,
313 switch_config_failed = 10
314 ),
315
316 # version 1.2
317 of_g.VERSION_1_2:dict(
318 hello_failed = 0,
319 bad_request = 1,
320 bad_action = 2,
321 bad_instruction = 3,
322 bad_match = 4,
323 flow_mod_failed = 5,
324 group_mod_failed = 6,
325 port_mod_failed = 7,
326 table_mod_failed = 8,
327 queue_op_failed = 9,
328 switch_config_failed = 10,
329 role_request_failed = 11,
330 experimenter = 0xffff
331 ),
332
333 # version 1.3
334 of_g.VERSION_1_3:dict(
335 hello_failed = 0,
336 bad_request = 1,
337 bad_action = 2,
338 bad_instruction = 3,
339 bad_match = 4,
340 flow_mod_failed = 5,
341 group_mod_failed = 6,
342 port_mod_failed = 7,
343 table_mod_failed = 8,
344 queue_op_failed = 9,
345 switch_config_failed = 10,
346 role_request_failed = 11,
347 meter_mod_failed = 12,
348 table_features_failed= 13,
349 experimenter = 0xffff
350 )
351 }
352
353##
354# These are the objects whose length is specified by an external
355# reference, specifically another data member in the class.
Andreas Wundsam53256162013-05-02 14:05:53 -0700356#
Rich Lanea06d0c32013-03-25 08:52:03 -0700357#external_length_spec = {
358# ("of_packet_out", "actions", OF_VERSION_1_0) : "actions_len",
359# ("of_packet_out", "actions", OF_VERSION_1_1) : "actions_len",
360# ("of_packet_out", "actions", OF_VERSION_1_2) : "actions_len",
361# ("of_packet_out", "actions", OF_VERSION_1_3) : "actions_len"
362#}
363
364
365################################################################
366#
Andreas Wundsam53256162013-05-02 14:05:53 -0700367# type_val is the primary data structure that maps an
Rich Lanea06d0c32013-03-25 08:52:03 -0700368# (class_name, version) pair to the wire data type value
369#
370################################################################
371
372type_val = dict()
Rich Lane6bb28dd2013-05-13 15:19:14 -0700373inheritance_map = dict()
Rich Lanea06d0c32013-03-25 08:52:03 -0700374
Rich Lane6bb28dd2013-05-13 15:19:14 -0700375def generate_maps():
376 for parent, versioned in inheritance_data.items():
377 inheritance_map[parent] = set()
378 for ver, subclasses in versioned.items():
379 for subcls in subclasses:
380 inheritance_map[parent].add(subcls)
Rich Lanea06d0c32013-03-25 08:52:03 -0700381
Rich Lane6bb28dd2013-05-13 15:19:14 -0700382 for version, classes in message_types.items():
383 for cls in classes:
384 name = "of_" + cls
385 type_val[(name, version)] = classes[cls]
Rich Lanea06d0c32013-03-25 08:52:03 -0700386
Rich Lane6bb28dd2013-05-13 15:19:14 -0700387 for parent, versioned in inheritance_data.items():
388 for version, subclasses in versioned.items():
389 for subcls, value in subclasses.items():
390 name = parent + "_" + subcls
391 type_val[(name, version)] = value
392
393 # Special case OF-1.2 match type
Rich Lanea72c98e2013-07-12 16:40:06 -0700394 type_val[("of_match_v3", of_g.VERSION_1_2)] = 1
395 type_val[("of_match_v3", of_g.VERSION_1_3)] = 1
Rich Lanea06d0c32013-03-25 08:52:03 -0700396
397# Utility function
398def dict_to_array(d, m_val, def_val=-1):
399 """
400 Given a dictionary, d, with each value a small integer,
401 produce an array indexed by the integer whose value is the key.
402 @param d The dictionary
403 @param m_val Ignore values greater than m_val
404 @param def_val The default value (for indices not in range of d)
405 """
406
407 # Get the max value in range for hash
408 max_val = 0
409 for key in d:
410 if (d[key] > max_val) and (d[key] < m_val):
411 max_val = d[key]
412 ar = []
413 for x in range(0, max_val + 1):
414 ar.append(def_val)
415 for key in d:
416 if (d[key] < m_val):
417 ar[d[key]] = key
418 return ar
419
420def type_array_len(version_indexed, max_val):
421 """
422 Given versioned information about a type, calculate how long
423 the unified array should be.
424
Andreas Wundsam53256162013-05-02 14:05:53 -0700425 @param version_indexed A dict indexed by version. Each value is a
Rich Lanea06d0c32013-03-25 08:52:03 -0700426 dict indexed by a name and whose value is an integer
427 @param max_val Ignore values greater than this for length calcs
428 """
429 # First, find the max length of all arrays
430 arr_len = 0
431 for version, val_dict in version_indexed.items():
432 ar = dict_to_array(val_dict, max_val, invalid_type)
433 if arr_len < len(ar):
434 arr_len = len(ar)
435 return arr_len
436
437# FIXME: Need to move update for multipart messages
438
439stats_reply_list = [
440 "of_aggregate_stats_reply",
441 "of_desc_stats_reply",
442 "of_experimenter_stats_reply",
443 "of_flow_stats_reply",
444 "of_group_stats_reply",
445 "of_group_desc_stats_reply",
446 "of_group_features_stats_reply",
447 "of_meter_stats_reply",
448 "of_meter_config_stats_reply",
449 "of_meter_features_stats_reply",
450 "of_port_stats_reply",
451 "of_port_desc_stats_reply",
452 "of_queue_stats_reply",
453 "of_table_stats_reply",
454 "of_table_features_stats_reply"
455]
456
457stats_request_list = [
458 "of_aggregate_stats_request",
459 "of_desc_stats_request",
460 "of_experimenter_stats_request",
461 "of_flow_stats_request",
462 "of_group_stats_request",
463 "of_group_desc_stats_request",
464 "of_group_features_stats_request",
465 "of_meter_stats_request",
466 "of_meter_config_stats_request",
467 "of_meter_features_stats_request",
468 "of_port_stats_request",
469 "of_port_desc_stats_request",
470 "of_queue_stats_request",
471 "of_table_stats_request",
472 "of_table_features_stats_request"
473]
474
475flow_mod_list = [
476 "of_flow_add",
477 "of_flow_modify",
478 "of_flow_modify_strict",
479 "of_flow_delete",
480 "of_flow_delete_strict"
481]
482
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700483error_msg_list = [
484 "of_hello_failed_error_msg",
485 "of_bad_request_error_msg",
486 "of_bad_action_error_msg",
487 "of_bad_instruction_error_msg",
488 "of_bad_match_error_msg",
489 "of_flow_mod_failed_error_msg",
490 "of_group_mod_failed_error_msg",
491 "of_port_mod_failed_error_msg",
492 "of_table_mod_failed_error_msg",
493 "of_queue_op_failed_error_msg",
494 "of_switch_config_failed_error_msg",
495 "of_role_request_failed_error_msg",
496 "of_meter_mod_failed_error_msg",
497 "of_table_features_failed_error_msg",
498 "of_experimenter_error_msg"
499]
500
Rich Lanea06d0c32013-03-25 08:52:03 -0700501def sub_class_map(base_type, version):
502 """
503 Returns an iterable object giving the instance nameys and subclass types
504 for the base_type, version values
505 """
506 rv = []
507 if base_type not in inheritance_map:
508 return rv
509
510 for instance in inheritance_map[base_type]:
511 subcls = loxi_utils.instance_to_class(instance, base_type)
512 if not loxi_utils.class_in_version(subcls, version):
513 continue
514 rv.append((instance, subcls))
515
516 return rv
517
518################################################################
519#
520# Extension related data and functions
521#
522################################################################
523
524# Per OF Version, per experimenter, map exp msg type (subtype) to object IDs
525# @fixme Generate defines for OF_<exp>_SUBTYPE_<msg> for the values below?
526extension_message_subtype = {
527 # version 1.0
528 of_g.VERSION_1_0:dict( # Version 1.0 extensions
529 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700530 },
531 nicira = { # Nicira extensions, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700532 },
533 ),
534 of_g.VERSION_1_1:dict( # Version 1.0 extensions
535 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700536 },
537 ),
538 of_g.VERSION_1_2:dict( # Version 1.0 extensions
539 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700540 },
541 ),
542 of_g.VERSION_1_3:dict( # Version 1.0 extensions
543 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700544 },
545 ),
546}
547
548# Set to empty dict if no extension actions defined
549# Per OF Version, per experimenter, map actions to subtype
550extension_action_subtype = {
551 # version 1.0
552 of_g.VERSION_1_0:dict( # Version 1.0 extensions
553 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700554 },
555 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700556 }
557 ),
558 of_g.VERSION_1_1:dict( # Version 1.0 extensions
559 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700560 },
561 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700562 }
563 ),
564 of_g.VERSION_1_2:dict( # Version 1.0 extensions
565 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700566 },
567 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700568 }
569 ),
570 of_g.VERSION_1_3:dict( # Version 1.0 extensions
571 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700572 },
573 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700574 }
575 ),
576}
577
578# Set to empty dict if no extension actions defined
579# Per OF Version, per experimenter, map actions to subtype
580extension_action_id_subtype = {
581 # version 1.0
582 of_g.VERSION_1_0:dict(),
583 of_g.VERSION_1_1:dict(),
584 of_g.VERSION_1_2:dict(),
585 of_g.VERSION_1_3:dict( # Version 1.3 extensions
586 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700587 },
588 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700589 }
590 ),
591}
592
593# Set to empty dict if no extension instructions defined
594extension_instruction_subtype = {}
595
596# Set to empty dict if no extension instructions defined
597extension_queue_prop_subtype = {}
598
599# Set to empty dict if no extension instructions defined
600extension_table_feature_prop_subtype = {}
601
602extension_objects = [
603 extension_message_subtype,
604 extension_action_subtype,
605 extension_action_id_subtype,
606 extension_instruction_subtype,
607 extension_queue_prop_subtype,
608 extension_table_feature_prop_subtype
609]
610
611################################################################
612# These are extension type generic (for messages, actions...)
613################################################################
614
615def extension_to_experimenter_name(cls):
616 """
617 Return the name of the experimenter if class is an
618 extension, else None
619
620 This is brute force; we search all extension data for a match
621 """
Andreas Wundsam53256162013-05-02 14:05:53 -0700622
Rich Lanea06d0c32013-03-25 08:52:03 -0700623 for ext_obj in extension_objects:
624 for version, exp_list in ext_obj.items():
625 for exp_name, classes in exp_list.items():
626 if cls in classes:
627 return exp_name
628 return None
629
630def extension_to_experimenter_id(cls):
631 """
632 Return the ID of the experimenter if class is an
633 extension, else None
634 """
635 exp_name = extension_to_experimenter_name(cls)
636 if exp_name:
637 return of_g.experimenter_name_to_id[exp_name]
638 return None
639
640def extension_to_experimenter_macro_name(cls):
641 """
642 Return the "macro name" of the ID of the experimenter if class is an
643 extension, else None
644 """
645 exp_name = extension_to_experimenter_name(cls)
646 if exp_name:
647 return "OF_EXPERIMENTER_ID_" + exp_name.upper()
648 return None
649
650def extension_to_subtype(cls, version):
651 """
652 Generic across all extension objects, return subtype identifier
653 """
654 for ext_obj in extension_objects:
655 for version, exp_list in ext_obj.items():
656 for exp_name, classes in exp_list.items():
657 if cls in classes:
658 return classes[cls]
659
660def class_is_extension(cls, version):
661 """
662 Return True if class, version is recognized as an extension
663 of any type (message, action....)
664
665 Accepts of_g.OF_VERSION_ANY
666 """
667
668 for ext_obj in extension_objects:
669 if cls_is_ext_obj(cls, version, ext_obj):
670 return True
671
672 return False
673
674# Internal
675def cls_is_ext_obj(cls, version, ext_obj):
676 """
677 @brief Return True if cls in an extension of type ext_obj
678 @param cls The class to check
679 @param version The version to check
680 @param ext_obj The extension object dictionary (messages, actions...)
681
682 Accepts of_g.VERSION_ANY
683 """
684
685 # Call with each version if "any" is passed
686 if version == of_g.VERSION_ANY:
687 for v in of_g.of_version_range:
688 if cls_is_ext_obj(cls, v, ext_obj):
689 return True
690 else: # Version specified
691 if version in ext_obj:
692 for exp, subtype_vals in ext_obj[version].items():
693 if cls in subtype_vals:
694 return True
695
696 return False
Andreas Wundsam53256162013-05-02 14:05:53 -0700697
Rich Lanea06d0c32013-03-25 08:52:03 -0700698################################################################
699# These are extension message specific
700################################################################
701
702def message_is_extension(cls, version):
703 """
704 Return True if cls, version is recognized as an extension
705 This is brute force, searching records for a match
706 """
707 return cls_is_ext_obj(cls, version, extension_message_subtype)
708
709def extension_message_to_subtype(cls, version):
710 """
711 Return the subtype of the experimenter message if the class is an
712 extension, else None
713 """
714 if version in extension_message_subtype:
715 for exp, classes in extension_message_subtype[version].items():
716 for ext_class, subtype in classes.items():
717 if cls == ext_class:
718 return subtype
719 return None
720
721################################################################
722# These are extension action specific
723################################################################
724
725def action_is_extension(cls, version):
726 """
727 Return True if cls, version is recognized as an action extension
728 This is brute force, searching records for a match
729 """
730 return cls_is_ext_obj(cls, version, extension_action_subtype)
731
732def extension_action_to_subtype(cls, version):
733 """
734 Return the ID of the action subtype (for its experimenteer)
735 if class is an action extension, else None
736 """
737 if version in extension_action_subtype:
738 for exp, classes in extension_action_subtype[version].items():
739 if cls in classes:
740 return classes[cls]
741
742 return None
743
744################################################################
745# These are extension action specific
746################################################################
747
748def action_id_is_extension(cls, version):
749 """
750 Return True if cls, version is recognized as an action ID extension
751 This is brute force, searching records for a match
752 """
753 if version not in [of_g.VERSION_1_3]: # Action IDs only 1.3
754 return False
755 return cls_is_ext_obj(cls, version, extension_action_id_subtype)
756
757def extension_action_id_to_subtype(cls, version):
758 """
759 Return the ID of the action ID subtype (for its experimenteer)
760 if class is an action ID extension, else None
761 """
762 if version in extension_action_id_subtype:
763 for exp, classes in extension_action_id_subtype[version].items():
764 if cls in classes:
765 return classes[cls]
766
767 return None
768
769################################################################
770# These are extension instruction specific
771################################################################
772
773def instruction_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, extension_instruction_subtype)
779
780################################################################
781# These are extension queue_prop specific
782################################################################
783
784def queue_prop_is_extension(cls, version):
785 """
786 Return True if cls, version is recognized as an instruction extension
787 This is brute force, searching records for a match
788 """
789 return cls_is_ext_obj(cls, version, extension_queue_prop_subtype)
790
791################################################################
792# These are extension table_feature_prop specific
793################################################################
794
795def table_feature_prop_is_extension(cls, version):
796 """
797 Return True if cls, version is recognized as an instruction extension
798 This is brute force, searching records for a match
799 """
800 return cls_is_ext_obj(cls, version,
801 extension_table_feature_prop_subtype)