blob: 2f02e939da9aa5a3415fcee614a2263750d0d9a2 [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
Rich Lane353a79f2013-11-13 10:39:56 -0800158 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", "of_bsn_stats_request", "of_bsn_stats_reply", "of_experimenter_stats_request", "of_experimenter_stats_reply"]:
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,
Rich Lane353a79f2013-11-13 10:39:56 -0800269 experimenter = 0xffff,
270 bsn_lacp = 0xffff
Rich Lanea06d0c32013-03-25 08:52:03 -0700271 )
272 }
273
274common_flow_mod_types = dict(
275 add = 0,
276 modify = 1,
277 modify_strict = 2,
278 delete = 3,
279 delete_strict = 4
280 )
281
282flow_mod_types = {
283 # version 1.0
284 of_g.VERSION_1_0:common_flow_mod_types,
285 of_g.VERSION_1_1:common_flow_mod_types,
286 of_g.VERSION_1_2:common_flow_mod_types,
287 of_g.VERSION_1_3:common_flow_mod_types
288 }
289
290# These do not translate to objects (yet)
291error_types = {
292 # version 1.0
293 of_g.VERSION_1_0:dict(
294 hello_failed = 0,
295 bad_request = 1,
296 bad_action = 2,
297 flow_mod_failed = 3,
298 port_mod_failed = 4,
299 queue_op_failed = 5
300 ),
301
302 # version 1.1
303 of_g.VERSION_1_1:dict(
304 hello_failed = 0,
305 bad_request = 1,
306 bad_action = 2,
307 bad_instruction = 3,
308 bad_match = 4,
309 flow_mod_failed = 5,
310 group_mod_failed = 6,
311 port_mod_failed = 7,
312 table_mod_failed = 8,
313 queue_op_failed = 9,
314 switch_config_failed = 10
315 ),
316
317 # version 1.2
318 of_g.VERSION_1_2:dict(
319 hello_failed = 0,
320 bad_request = 1,
321 bad_action = 2,
322 bad_instruction = 3,
323 bad_match = 4,
324 flow_mod_failed = 5,
325 group_mod_failed = 6,
326 port_mod_failed = 7,
327 table_mod_failed = 8,
328 queue_op_failed = 9,
329 switch_config_failed = 10,
330 role_request_failed = 11,
331 experimenter = 0xffff
332 ),
333
334 # version 1.3
335 of_g.VERSION_1_3:dict(
336 hello_failed = 0,
337 bad_request = 1,
338 bad_action = 2,
339 bad_instruction = 3,
340 bad_match = 4,
341 flow_mod_failed = 5,
342 group_mod_failed = 6,
343 port_mod_failed = 7,
344 table_mod_failed = 8,
345 queue_op_failed = 9,
346 switch_config_failed = 10,
347 role_request_failed = 11,
348 meter_mod_failed = 12,
349 table_features_failed= 13,
350 experimenter = 0xffff
351 )
352 }
353
354##
355# These are the objects whose length is specified by an external
356# reference, specifically another data member in the class.
Andreas Wundsam53256162013-05-02 14:05:53 -0700357#
Rich Lanea06d0c32013-03-25 08:52:03 -0700358#external_length_spec = {
359# ("of_packet_out", "actions", OF_VERSION_1_0) : "actions_len",
360# ("of_packet_out", "actions", OF_VERSION_1_1) : "actions_len",
361# ("of_packet_out", "actions", OF_VERSION_1_2) : "actions_len",
362# ("of_packet_out", "actions", OF_VERSION_1_3) : "actions_len"
363#}
364
365
366################################################################
367#
Andreas Wundsam53256162013-05-02 14:05:53 -0700368# type_val is the primary data structure that maps an
Rich Lanea06d0c32013-03-25 08:52:03 -0700369# (class_name, version) pair to the wire data type value
370#
371################################################################
372
373type_val = dict()
Rich Lane6bb28dd2013-05-13 15:19:14 -0700374inheritance_map = dict()
Rich Lanea06d0c32013-03-25 08:52:03 -0700375
Rich Lane6bb28dd2013-05-13 15:19:14 -0700376def generate_maps():
377 for parent, versioned in inheritance_data.items():
378 inheritance_map[parent] = set()
379 for ver, subclasses in versioned.items():
380 for subcls in subclasses:
381 inheritance_map[parent].add(subcls)
Rich Lanea06d0c32013-03-25 08:52:03 -0700382
Rich Lane6bb28dd2013-05-13 15:19:14 -0700383 for version, classes in message_types.items():
384 for cls in classes:
385 name = "of_" + cls
386 type_val[(name, version)] = classes[cls]
Rich Lanea06d0c32013-03-25 08:52:03 -0700387
Rich Lane6bb28dd2013-05-13 15:19:14 -0700388 for parent, versioned in inheritance_data.items():
389 for version, subclasses in versioned.items():
390 for subcls, value in subclasses.items():
391 name = parent + "_" + subcls
392 type_val[(name, version)] = value
393
394 # Special case OF-1.2 match type
Rich Lanea72c98e2013-07-12 16:40:06 -0700395 type_val[("of_match_v3", of_g.VERSION_1_2)] = 1
396 type_val[("of_match_v3", of_g.VERSION_1_3)] = 1
Rich Lanea06d0c32013-03-25 08:52:03 -0700397
398# Utility function
399def dict_to_array(d, m_val, def_val=-1):
400 """
401 Given a dictionary, d, with each value a small integer,
402 produce an array indexed by the integer whose value is the key.
403 @param d The dictionary
404 @param m_val Ignore values greater than m_val
405 @param def_val The default value (for indices not in range of d)
406 """
407
408 # Get the max value in range for hash
409 max_val = 0
410 for key in d:
411 if (d[key] > max_val) and (d[key] < m_val):
412 max_val = d[key]
413 ar = []
414 for x in range(0, max_val + 1):
415 ar.append(def_val)
416 for key in d:
417 if (d[key] < m_val):
418 ar[d[key]] = key
419 return ar
420
421def type_array_len(version_indexed, max_val):
422 """
423 Given versioned information about a type, calculate how long
424 the unified array should be.
425
Andreas Wundsam53256162013-05-02 14:05:53 -0700426 @param version_indexed A dict indexed by version. Each value is a
Rich Lanea06d0c32013-03-25 08:52:03 -0700427 dict indexed by a name and whose value is an integer
428 @param max_val Ignore values greater than this for length calcs
429 """
430 # First, find the max length of all arrays
431 arr_len = 0
432 for version, val_dict in version_indexed.items():
433 ar = dict_to_array(val_dict, max_val, invalid_type)
434 if arr_len < len(ar):
435 arr_len = len(ar)
436 return arr_len
437
438# FIXME: Need to move update for multipart messages
439
440stats_reply_list = [
441 "of_aggregate_stats_reply",
442 "of_desc_stats_reply",
443 "of_experimenter_stats_reply",
444 "of_flow_stats_reply",
445 "of_group_stats_reply",
446 "of_group_desc_stats_reply",
447 "of_group_features_stats_reply",
448 "of_meter_stats_reply",
449 "of_meter_config_stats_reply",
450 "of_meter_features_stats_reply",
451 "of_port_stats_reply",
452 "of_port_desc_stats_reply",
453 "of_queue_stats_reply",
454 "of_table_stats_reply",
Rich Lane353a79f2013-11-13 10:39:56 -0800455 "of_table_features_stats_reply",
456 "of_bsn_stats_reply",
457 "of_bsn_lacp_stats_reply",
Rich Lanea06d0c32013-03-25 08:52:03 -0700458]
459
460stats_request_list = [
461 "of_aggregate_stats_request",
462 "of_desc_stats_request",
463 "of_experimenter_stats_request",
464 "of_flow_stats_request",
465 "of_group_stats_request",
466 "of_group_desc_stats_request",
467 "of_group_features_stats_request",
468 "of_meter_stats_request",
469 "of_meter_config_stats_request",
470 "of_meter_features_stats_request",
471 "of_port_stats_request",
472 "of_port_desc_stats_request",
473 "of_queue_stats_request",
474 "of_table_stats_request",
Rich Lane353a79f2013-11-13 10:39:56 -0800475 "of_table_features_stats_request",
476 "of_bsn_stats_request",
477 "of_bsn_lacp_stats_request",
Rich Lanea06d0c32013-03-25 08:52:03 -0700478]
479
480flow_mod_list = [
481 "of_flow_add",
482 "of_flow_modify",
483 "of_flow_modify_strict",
484 "of_flow_delete",
485 "of_flow_delete_strict"
486]
487
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700488error_msg_list = [
489 "of_hello_failed_error_msg",
490 "of_bad_request_error_msg",
491 "of_bad_action_error_msg",
492 "of_bad_instruction_error_msg",
493 "of_bad_match_error_msg",
494 "of_flow_mod_failed_error_msg",
495 "of_group_mod_failed_error_msg",
496 "of_port_mod_failed_error_msg",
497 "of_table_mod_failed_error_msg",
498 "of_queue_op_failed_error_msg",
499 "of_switch_config_failed_error_msg",
500 "of_role_request_failed_error_msg",
501 "of_meter_mod_failed_error_msg",
502 "of_table_features_failed_error_msg",
503 "of_experimenter_error_msg"
504]
505
Rich Lanea06d0c32013-03-25 08:52:03 -0700506def sub_class_map(base_type, version):
507 """
508 Returns an iterable object giving the instance nameys and subclass types
509 for the base_type, version values
510 """
511 rv = []
512 if base_type not in inheritance_map:
513 return rv
514
515 for instance in inheritance_map[base_type]:
516 subcls = loxi_utils.instance_to_class(instance, base_type)
517 if not loxi_utils.class_in_version(subcls, version):
518 continue
519 rv.append((instance, subcls))
520
521 return rv
522
523################################################################
524#
525# Extension related data and functions
526#
527################################################################
528
529# Per OF Version, per experimenter, map exp msg type (subtype) to object IDs
530# @fixme Generate defines for OF_<exp>_SUBTYPE_<msg> for the values below?
531extension_message_subtype = {
532 # version 1.0
533 of_g.VERSION_1_0:dict( # Version 1.0 extensions
534 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700535 },
536 nicira = { # Nicira extensions, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700537 },
538 ),
539 of_g.VERSION_1_1:dict( # Version 1.0 extensions
540 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700541 },
542 ),
543 of_g.VERSION_1_2:dict( # Version 1.0 extensions
544 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700545 },
546 ),
547 of_g.VERSION_1_3:dict( # Version 1.0 extensions
548 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700549 },
550 ),
551}
552
553# Set to empty dict if no extension actions defined
554# Per OF Version, per experimenter, map actions to subtype
555extension_action_subtype = {
556 # version 1.0
557 of_g.VERSION_1_0:dict( # Version 1.0 extensions
558 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700559 },
560 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700561 }
562 ),
563 of_g.VERSION_1_1:dict( # Version 1.0 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 of_g.VERSION_1_2:dict( # Version 1.0 extensions
570 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700571 },
572 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700573 }
574 ),
575 of_g.VERSION_1_3:dict( # Version 1.0 extensions
576 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700577 },
578 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700579 }
580 ),
581}
582
583# Set to empty dict if no extension actions defined
584# Per OF Version, per experimenter, map actions to subtype
585extension_action_id_subtype = {
586 # version 1.0
587 of_g.VERSION_1_0:dict(),
588 of_g.VERSION_1_1:dict(),
589 of_g.VERSION_1_2:dict(),
590 of_g.VERSION_1_3:dict( # Version 1.3 extensions
591 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700592 },
593 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700594 }
595 ),
596}
597
598# Set to empty dict if no extension instructions defined
599extension_instruction_subtype = {}
600
601# Set to empty dict if no extension instructions defined
602extension_queue_prop_subtype = {}
603
604# Set to empty dict if no extension instructions defined
605extension_table_feature_prop_subtype = {}
606
607extension_objects = [
608 extension_message_subtype,
609 extension_action_subtype,
610 extension_action_id_subtype,
611 extension_instruction_subtype,
612 extension_queue_prop_subtype,
613 extension_table_feature_prop_subtype
614]
615
616################################################################
617# These are extension type generic (for messages, actions...)
618################################################################
619
620def extension_to_experimenter_name(cls):
621 """
622 Return the name of the experimenter if class is an
623 extension, else None
624
625 This is brute force; we search all extension data for a match
626 """
Andreas Wundsam53256162013-05-02 14:05:53 -0700627
Rich Lanea06d0c32013-03-25 08:52:03 -0700628 for ext_obj in extension_objects:
629 for version, exp_list in ext_obj.items():
630 for exp_name, classes in exp_list.items():
631 if cls in classes:
632 return exp_name
633 return None
634
635def extension_to_experimenter_id(cls):
636 """
637 Return the ID of the experimenter if class is an
638 extension, else None
639 """
640 exp_name = extension_to_experimenter_name(cls)
641 if exp_name:
642 return of_g.experimenter_name_to_id[exp_name]
643 return None
644
645def extension_to_experimenter_macro_name(cls):
646 """
647 Return the "macro name" of the ID of the experimenter if class is an
648 extension, else None
649 """
650 exp_name = extension_to_experimenter_name(cls)
651 if exp_name:
652 return "OF_EXPERIMENTER_ID_" + exp_name.upper()
653 return None
654
655def extension_to_subtype(cls, version):
656 """
657 Generic across all extension objects, return subtype identifier
658 """
659 for ext_obj in extension_objects:
660 for version, exp_list in ext_obj.items():
661 for exp_name, classes in exp_list.items():
662 if cls in classes:
663 return classes[cls]
664
665def class_is_extension(cls, version):
666 """
667 Return True if class, version is recognized as an extension
668 of any type (message, action....)
669
670 Accepts of_g.OF_VERSION_ANY
671 """
672
673 for ext_obj in extension_objects:
674 if cls_is_ext_obj(cls, version, ext_obj):
675 return True
676
677 return False
678
679# Internal
680def cls_is_ext_obj(cls, version, ext_obj):
681 """
682 @brief Return True if cls in an extension of type ext_obj
683 @param cls The class to check
684 @param version The version to check
685 @param ext_obj The extension object dictionary (messages, actions...)
686
687 Accepts of_g.VERSION_ANY
688 """
689
690 # Call with each version if "any" is passed
691 if version == of_g.VERSION_ANY:
692 for v in of_g.of_version_range:
693 if cls_is_ext_obj(cls, v, ext_obj):
694 return True
695 else: # Version specified
696 if version in ext_obj:
697 for exp, subtype_vals in ext_obj[version].items():
698 if cls in subtype_vals:
699 return True
700
701 return False
Andreas Wundsam53256162013-05-02 14:05:53 -0700702
Rich Lanea06d0c32013-03-25 08:52:03 -0700703################################################################
704# These are extension message specific
705################################################################
706
707def message_is_extension(cls, version):
708 """
709 Return True if cls, version is recognized as an extension
710 This is brute force, searching records for a match
711 """
712 return cls_is_ext_obj(cls, version, extension_message_subtype)
713
714def extension_message_to_subtype(cls, version):
715 """
716 Return the subtype of the experimenter message if the class is an
717 extension, else None
718 """
719 if version in extension_message_subtype:
720 for exp, classes in extension_message_subtype[version].items():
721 for ext_class, subtype in classes.items():
722 if cls == ext_class:
723 return subtype
724 return None
725
726################################################################
727# These are extension action specific
728################################################################
729
730def action_is_extension(cls, version):
731 """
732 Return True if cls, version is recognized as an action extension
733 This is brute force, searching records for a match
734 """
735 return cls_is_ext_obj(cls, version, extension_action_subtype)
736
737def extension_action_to_subtype(cls, version):
738 """
739 Return the ID of the action subtype (for its experimenteer)
740 if class is an action extension, else None
741 """
742 if version in extension_action_subtype:
743 for exp, classes in extension_action_subtype[version].items():
744 if cls in classes:
745 return classes[cls]
746
747 return None
748
749################################################################
750# These are extension action specific
751################################################################
752
753def action_id_is_extension(cls, version):
754 """
755 Return True if cls, version is recognized as an action ID extension
756 This is brute force, searching records for a match
757 """
758 if version not in [of_g.VERSION_1_3]: # Action IDs only 1.3
759 return False
760 return cls_is_ext_obj(cls, version, extension_action_id_subtype)
761
762def extension_action_id_to_subtype(cls, version):
763 """
764 Return the ID of the action ID subtype (for its experimenteer)
765 if class is an action ID extension, else None
766 """
767 if version in extension_action_id_subtype:
768 for exp, classes in extension_action_id_subtype[version].items():
769 if cls in classes:
770 return classes[cls]
771
772 return None
773
774################################################################
775# These are extension instruction specific
776################################################################
777
778def instruction_is_extension(cls, version):
779 """
780 Return True if cls, version is recognized as an instruction extension
781 This is brute force, searching records for a match
782 """
783 return cls_is_ext_obj(cls, version, extension_instruction_subtype)
784
785################################################################
786# These are extension queue_prop specific
787################################################################
788
789def queue_prop_is_extension(cls, version):
790 """
791 Return True if cls, version is recognized as an instruction extension
792 This is brute force, searching records for a match
793 """
794 return cls_is_ext_obj(cls, version, extension_queue_prop_subtype)
795
796################################################################
797# These are extension table_feature_prop specific
798################################################################
799
800def table_feature_prop_is_extension(cls, version):
801 """
802 Return True if cls, version is recognized as an instruction extension
803 This is brute force, searching records for a match
804 """
805 return cls_is_ext_obj(cls, version,
806 extension_table_feature_prop_subtype)