blob: 14e7048c1fb43304112e9c53d38bf2247749f8fa [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
Andreas Wundsam542a13c2013-11-15 13:28:55 -080036import c_gen.of_g_legacy as of_g
Rich Lanea06d0c32013-03-25 08:52:03 -070037import sys
38from generic_utils import *
Rich Lanea06d0c32013-03-25 08:52:03 -070039import loxi_utils.loxi_utils as loxi_utils
Andreas Wundsam542a13c2013-11-15 13:28:55 -080040import c_gen.loxi_utils_legacy as loxi_utils
Rich Lanea06d0c32013-03-25 08:52:03 -070041
42invalid_type = "invalid_type"
43invalid_value = "0xeeee" # Note, as a string
44
45################################################################
46#
47# Define type data for inheritance classes:
48# instructions, actions, queue properties and OXM
49#
50# Messages are not in this group; they're treated specially for now
51#
52# These are indexed by wire protocol number
53#
54################################################################
55
56instruction_types = {
Rich Lanea06d0c32013-03-25 08:52:03 -070057 of_g.VERSION_1_0:dict(),
Rich Lane4db4d042013-05-13 18:13:48 -070058 of_g.VERSION_1_1:dict(),
59 of_g.VERSION_1_2:dict(),
60 of_g.VERSION_1_3:dict()
Rich Lanea06d0c32013-03-25 08:52:03 -070061 }
62
Rich Lane4db4d042013-05-13 18:13:48 -070063# HACK shared between actions and action_ids
64of_1_3_action_types = dict()
Rich Lanea06d0c32013-03-25 08:52:03 -070065
Rich Lanea06d0c32013-03-25 08:52:03 -070066action_types = {
Rich Lane4db4d042013-05-13 18:13:48 -070067 of_g.VERSION_1_0:dict(),
68 of_g.VERSION_1_1:dict(),
69 of_g.VERSION_1_2:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -070070 of_g.VERSION_1_3:of_1_3_action_types
Rich Lanea06d0c32013-03-25 08:52:03 -070071 }
72
73action_id_types = {
Rich Lanea06d0c32013-03-25 08:52:03 -070074 of_g.VERSION_1_0:dict(),
75 of_g.VERSION_1_1:dict(),
76 of_g.VERSION_1_2:dict(),
77 of_g.VERSION_1_3:of_1_3_action_types
78 }
79
80queue_prop_types = {
Rich Lane4db4d042013-05-13 18:13:48 -070081 of_g.VERSION_1_0:dict(),
82 of_g.VERSION_1_1:dict(),
83 of_g.VERSION_1_2:dict(),
84 of_g.VERSION_1_3:dict()
Rich Lanea06d0c32013-03-25 08:52:03 -070085 }
86
Dan Talaycoc0e802e2013-05-18 23:52:39 -070087bsn_vport_types = {
88 # version 1.0
89 of_g.VERSION_1_0:dict(
90 q_in_q = 0,
91 ),
92 # version 1.1
93 of_g.VERSION_1_1:dict(
94 q_in_q = 0,
95 ),
96 # version 1.2
97 of_g.VERSION_1_2:dict(
98 q_in_q = 0,
99 ),
100 # version 1.3
101 of_g.VERSION_1_3:dict(
102 q_in_q = 0,
103 )
104 }
105
Rich Lanea06d0c32013-03-25 08:52:03 -0700106oxm_types = {
Rich Lanea06d0c32013-03-25 08:52:03 -0700107 of_g.VERSION_1_0:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700108 of_g.VERSION_1_1:dict(),
Rich Lane4db4d042013-05-13 18:13:48 -0700109 of_g.VERSION_1_2:dict(),
110 of_g.VERSION_1_3:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700111 }
112
113hello_elem_types = {
Rich Lanea06d0c32013-03-25 08:52:03 -0700114 of_g.VERSION_1_0:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700115 of_g.VERSION_1_1:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700116 of_g.VERSION_1_2:dict(),
Rich Lane4db4d042013-05-13 18:13:48 -0700117 of_g.VERSION_1_3:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700118 }
119
120table_feature_prop_types = {
Rich Lanea06d0c32013-03-25 08:52:03 -0700121 of_g.VERSION_1_0:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700122 of_g.VERSION_1_1:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700123 of_g.VERSION_1_2:dict(),
Rich Lane4db4d042013-05-13 18:13:48 -0700124 of_g.VERSION_1_3:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700125 }
126
127meter_band_types = {
Rich Lanea06d0c32013-03-25 08:52:03 -0700128 of_g.VERSION_1_0:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700129 of_g.VERSION_1_1:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700130 of_g.VERSION_1_2:dict(),
Rich Lane4db4d042013-05-13 18:13:48 -0700131 of_g.VERSION_1_3:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700132 }
133
134# All inheritance data for non-messages
135inheritance_data = dict(
136 of_instruction = instruction_types,
137 of_action = action_types,
138 of_action_id = action_id_types,
139 of_oxm = oxm_types,
140 of_queue_prop = queue_prop_types,
141 of_hello_elem = hello_elem_types,
142 of_table_feature_prop = table_feature_prop_types,
Dan Talaycoc0e802e2013-05-18 23:52:39 -0700143 of_meter_band = meter_band_types,
144 # BSN specific inheritance extensions
145 of_bsn_vport = bsn_vport_types
Rich Lanea06d0c32013-03-25 08:52:03 -0700146 )
147
Rich Lanea06d0c32013-03-25 08:52:03 -0700148def class_is_virtual(cls):
149 """
150 Returns True if cls is a virtual class
151 """
152 if cls in inheritance_map:
153 return True
154 if cls.find("header") > 0:
155 return True
156 if loxi_utils.class_is_list(cls):
157 return True
Rich Lane488b3c52013-06-21 18:11:02 -0700158 # TODO get this from the input file when we have virtual class syntax
Rich Laneef7b9942013-11-18 16:29:28 -0800159 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", "of_instruction_experimenter", "of_instruction_bsn"]:
Rich Lane488b3c52013-06-21 18:11:02 -0700160 return True
Rich Lanea06d0c32013-03-25 08:52:03 -0700161 return False
162
163################################################################
164#
165# These are message types
166#
167################################################################
168
Rich Lanedf847e32013-05-29 16:57:30 -0700169# The hardcoded message types are for inheritance parents
Rich Lanea06d0c32013-03-25 08:52:03 -0700170message_types = {
171 # version 1.0
172 of_g.VERSION_1_0:dict(
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700173 error_msg = 1,
Rich Lanedf847e32013-05-29 16:57:30 -0700174 experimenter = 4,
Rich Lanea06d0c32013-03-25 08:52:03 -0700175 flow_mod = 14,
Rich Lanea06d0c32013-03-25 08:52:03 -0700176 stats_request = 16,
177 stats_reply = 17,
Rich Lanea06d0c32013-03-25 08:52:03 -0700178 ),
179
180 # version 1.1
181 of_g.VERSION_1_1:dict(
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700182 error_msg = 1,
Rich Lanedf847e32013-05-29 16:57:30 -0700183 experimenter = 4,
Rich Lanea06d0c32013-03-25 08:52:03 -0700184 flow_mod = 14,
Rich Lanea06d0c32013-03-25 08:52:03 -0700185 stats_request = 18,
186 stats_reply = 19,
Rich Lanea06d0c32013-03-25 08:52:03 -0700187 ),
188
189 # version 1.2
190 of_g.VERSION_1_2:dict(
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700191 error_msg = 1,
Rich Lanedf847e32013-05-29 16:57:30 -0700192 experimenter = 4,
Rich Lanea06d0c32013-03-25 08:52:03 -0700193 flow_mod = 14,
Rich Lanea06d0c32013-03-25 08:52:03 -0700194 stats_request = 18,
195 stats_reply = 19,
Rich Lanea06d0c32013-03-25 08:52:03 -0700196 ),
197
198 # version 1.3
199 of_g.VERSION_1_3:dict(
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700200 error_msg = 1,
Rich Lanedf847e32013-05-29 16:57:30 -0700201 experimenter = 4,
Rich Lanea06d0c32013-03-25 08:52:03 -0700202 flow_mod = 14,
Rich Lanea06d0c32013-03-25 08:52:03 -0700203 stats_request = 18, # FIXME Multipart
204 stats_reply = 19,
Rich Lanea06d0c32013-03-25 08:52:03 -0700205 )
206 }
207
208################################################################
209#
210# These are other objects that have a notion of type but are
211# not (yet) promoted to objects with inheritance
212#
213################################################################
214
215stats_types = {
216 # version 1.0
217 of_g.VERSION_1_0:dict(
218 desc = 0,
219 flow = 1,
220 aggregate = 2,
221 table = 3,
222 port = 4,
223 queue = 5,
224 experimenter = 0xffff
225 ),
226
227 # version 1.1
228 of_g.VERSION_1_1:dict(
229 desc = 0,
230 flow = 1,
231 aggregate = 2,
232 table = 3,
233 port = 4,
234 queue = 5,
235 group = 6,
236 group_desc = 7,
237 experimenter = 0xffff
238 ),
239
240 # version 1.2
241 of_g.VERSION_1_2:dict(
242 desc = 0,
243 flow = 1,
244 aggregate = 2,
245 table = 3,
246 port = 4,
247 queue = 5,
248 group = 6,
249 group_desc = 7,
250 group_features = 8,
251 experimenter = 0xffff
252 ),
253
254 # version 1.3
255 of_g.VERSION_1_3:dict(
256 desc = 0,
257 flow = 1,
258 aggregate = 2,
259 table = 3,
260 port = 4,
261 queue = 5,
262 group = 6,
263 group_desc = 7,
264 group_features = 8,
265 meter = 9,
266 meter_config = 10,
267 meter_features = 11,
268 table_features = 12,
269 port_desc = 13,
Rich Lane353a79f2013-11-13 10:39:56 -0800270 experimenter = 0xffff,
Wilson Ng45386fb2013-12-03 13:46:42 -0800271 bsn_lacp = 0xffff,
272 bsn_switch_pipeline = 0xffff
Rich Lanea06d0c32013-03-25 08:52:03 -0700273 )
274 }
275
276common_flow_mod_types = dict(
277 add = 0,
278 modify = 1,
279 modify_strict = 2,
280 delete = 3,
281 delete_strict = 4
282 )
283
284flow_mod_types = {
285 # version 1.0
286 of_g.VERSION_1_0:common_flow_mod_types,
287 of_g.VERSION_1_1:common_flow_mod_types,
288 of_g.VERSION_1_2:common_flow_mod_types,
289 of_g.VERSION_1_3:common_flow_mod_types
290 }
291
292# These do not translate to objects (yet)
293error_types = {
294 # version 1.0
295 of_g.VERSION_1_0:dict(
296 hello_failed = 0,
297 bad_request = 1,
298 bad_action = 2,
299 flow_mod_failed = 3,
300 port_mod_failed = 4,
301 queue_op_failed = 5
302 ),
303
304 # version 1.1
305 of_g.VERSION_1_1:dict(
306 hello_failed = 0,
307 bad_request = 1,
308 bad_action = 2,
309 bad_instruction = 3,
310 bad_match = 4,
311 flow_mod_failed = 5,
312 group_mod_failed = 6,
313 port_mod_failed = 7,
314 table_mod_failed = 8,
315 queue_op_failed = 9,
316 switch_config_failed = 10
317 ),
318
319 # version 1.2
320 of_g.VERSION_1_2:dict(
321 hello_failed = 0,
322 bad_request = 1,
323 bad_action = 2,
324 bad_instruction = 3,
325 bad_match = 4,
326 flow_mod_failed = 5,
327 group_mod_failed = 6,
328 port_mod_failed = 7,
329 table_mod_failed = 8,
330 queue_op_failed = 9,
331 switch_config_failed = 10,
332 role_request_failed = 11,
333 experimenter = 0xffff
334 ),
335
336 # version 1.3
337 of_g.VERSION_1_3:dict(
338 hello_failed = 0,
339 bad_request = 1,
340 bad_action = 2,
341 bad_instruction = 3,
342 bad_match = 4,
343 flow_mod_failed = 5,
344 group_mod_failed = 6,
345 port_mod_failed = 7,
346 table_mod_failed = 8,
347 queue_op_failed = 9,
348 switch_config_failed = 10,
349 role_request_failed = 11,
350 meter_mod_failed = 12,
351 table_features_failed= 13,
352 experimenter = 0xffff
353 )
354 }
355
356##
357# These are the objects whose length is specified by an external
358# reference, specifically another data member in the class.
Andreas Wundsam53256162013-05-02 14:05:53 -0700359#
Rich Lanea06d0c32013-03-25 08:52:03 -0700360#external_length_spec = {
361# ("of_packet_out", "actions", OF_VERSION_1_0) : "actions_len",
362# ("of_packet_out", "actions", OF_VERSION_1_1) : "actions_len",
363# ("of_packet_out", "actions", OF_VERSION_1_2) : "actions_len",
364# ("of_packet_out", "actions", OF_VERSION_1_3) : "actions_len"
365#}
366
367
368################################################################
369#
Andreas Wundsam53256162013-05-02 14:05:53 -0700370# type_val is the primary data structure that maps an
Rich Lanea06d0c32013-03-25 08:52:03 -0700371# (class_name, version) pair to the wire data type value
372#
373################################################################
374
375type_val = dict()
Rich Lane6bb28dd2013-05-13 15:19:14 -0700376inheritance_map = dict()
Rich Lanea06d0c32013-03-25 08:52:03 -0700377
Rich Lane6bb28dd2013-05-13 15:19:14 -0700378def generate_maps():
379 for parent, versioned in inheritance_data.items():
380 inheritance_map[parent] = set()
381 for ver, subclasses in versioned.items():
382 for subcls in subclasses:
383 inheritance_map[parent].add(subcls)
Rich Lanea06d0c32013-03-25 08:52:03 -0700384
Rich Lane6bb28dd2013-05-13 15:19:14 -0700385 for version, classes in message_types.items():
386 for cls in classes:
387 name = "of_" + cls
388 type_val[(name, version)] = classes[cls]
Rich Lanea06d0c32013-03-25 08:52:03 -0700389
Rich Lane6bb28dd2013-05-13 15:19:14 -0700390 for parent, versioned in inheritance_data.items():
391 for version, subclasses in versioned.items():
392 for subcls, value in subclasses.items():
393 name = parent + "_" + subcls
394 type_val[(name, version)] = value
395
396 # Special case OF-1.2 match type
Rich Lanea72c98e2013-07-12 16:40:06 -0700397 type_val[("of_match_v3", of_g.VERSION_1_2)] = 1
398 type_val[("of_match_v3", of_g.VERSION_1_3)] = 1
Rich Lanea06d0c32013-03-25 08:52:03 -0700399
400# Utility function
401def dict_to_array(d, m_val, def_val=-1):
402 """
403 Given a dictionary, d, with each value a small integer,
404 produce an array indexed by the integer whose value is the key.
405 @param d The dictionary
406 @param m_val Ignore values greater than m_val
407 @param def_val The default value (for indices not in range of d)
408 """
409
410 # Get the max value in range for hash
411 max_val = 0
412 for key in d:
413 if (d[key] > max_val) and (d[key] < m_val):
414 max_val = d[key]
415 ar = []
416 for x in range(0, max_val + 1):
417 ar.append(def_val)
418 for key in d:
419 if (d[key] < m_val):
420 ar[d[key]] = key
421 return ar
422
423def type_array_len(version_indexed, max_val):
424 """
425 Given versioned information about a type, calculate how long
426 the unified array should be.
427
Andreas Wundsam53256162013-05-02 14:05:53 -0700428 @param version_indexed A dict indexed by version. Each value is a
Rich Lanea06d0c32013-03-25 08:52:03 -0700429 dict indexed by a name and whose value is an integer
430 @param max_val Ignore values greater than this for length calcs
431 """
432 # First, find the max length of all arrays
433 arr_len = 0
434 for version, val_dict in version_indexed.items():
435 ar = dict_to_array(val_dict, max_val, invalid_type)
436 if arr_len < len(ar):
437 arr_len = len(ar)
438 return arr_len
439
440# FIXME: Need to move update for multipart messages
441
442stats_reply_list = [
443 "of_aggregate_stats_reply",
444 "of_desc_stats_reply",
445 "of_experimenter_stats_reply",
446 "of_flow_stats_reply",
447 "of_group_stats_reply",
448 "of_group_desc_stats_reply",
449 "of_group_features_stats_reply",
450 "of_meter_stats_reply",
451 "of_meter_config_stats_reply",
452 "of_meter_features_stats_reply",
453 "of_port_stats_reply",
454 "of_port_desc_stats_reply",
455 "of_queue_stats_reply",
456 "of_table_stats_reply",
Rich Lane353a79f2013-11-13 10:39:56 -0800457 "of_table_features_stats_reply",
458 "of_bsn_stats_reply",
459 "of_bsn_lacp_stats_reply",
Wilson Ng27e4beb2013-12-03 12:33:01 -0800460 "of_bsn_switch_pipeline_stats_reply",
Rich Lanea06d0c32013-03-25 08:52:03 -0700461]
462
463stats_request_list = [
464 "of_aggregate_stats_request",
465 "of_desc_stats_request",
466 "of_experimenter_stats_request",
467 "of_flow_stats_request",
468 "of_group_stats_request",
469 "of_group_desc_stats_request",
470 "of_group_features_stats_request",
471 "of_meter_stats_request",
472 "of_meter_config_stats_request",
473 "of_meter_features_stats_request",
474 "of_port_stats_request",
475 "of_port_desc_stats_request",
476 "of_queue_stats_request",
477 "of_table_stats_request",
Rich Lane353a79f2013-11-13 10:39:56 -0800478 "of_table_features_stats_request",
479 "of_bsn_stats_request",
480 "of_bsn_lacp_stats_request",
Wilson Ng27e4beb2013-12-03 12:33:01 -0800481 "of_bsn_switch_pipeline_stats_request",
Rich Lanea06d0c32013-03-25 08:52:03 -0700482]
483
484flow_mod_list = [
485 "of_flow_add",
486 "of_flow_modify",
487 "of_flow_modify_strict",
488 "of_flow_delete",
489 "of_flow_delete_strict"
490]
491
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700492error_msg_list = [
493 "of_hello_failed_error_msg",
494 "of_bad_request_error_msg",
495 "of_bad_action_error_msg",
496 "of_bad_instruction_error_msg",
497 "of_bad_match_error_msg",
498 "of_flow_mod_failed_error_msg",
499 "of_group_mod_failed_error_msg",
500 "of_port_mod_failed_error_msg",
501 "of_table_mod_failed_error_msg",
502 "of_queue_op_failed_error_msg",
503 "of_switch_config_failed_error_msg",
504 "of_role_request_failed_error_msg",
505 "of_meter_mod_failed_error_msg",
506 "of_table_features_failed_error_msg",
507 "of_experimenter_error_msg"
508]
509
Rich Lanea06d0c32013-03-25 08:52:03 -0700510def sub_class_map(base_type, version):
511 """
512 Returns an iterable object giving the instance nameys and subclass types
513 for the base_type, version values
514 """
515 rv = []
516 if base_type not in inheritance_map:
517 return rv
518
519 for instance in inheritance_map[base_type]:
520 subcls = loxi_utils.instance_to_class(instance, base_type)
521 if not loxi_utils.class_in_version(subcls, version):
522 continue
523 rv.append((instance, subcls))
524
525 return rv
526
527################################################################
528#
529# Extension related data and functions
530#
531################################################################
532
533# Per OF Version, per experimenter, map exp msg type (subtype) to object IDs
534# @fixme Generate defines for OF_<exp>_SUBTYPE_<msg> for the values below?
535extension_message_subtype = {
536 # version 1.0
537 of_g.VERSION_1_0:dict( # Version 1.0 extensions
538 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700539 },
540 nicira = { # Nicira extensions, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700541 },
542 ),
543 of_g.VERSION_1_1: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_2: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 of_g.VERSION_1_3:dict( # Version 1.0 extensions
552 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700553 },
554 ),
555}
556
557# Set to empty dict if no extension actions defined
558# Per OF Version, per experimenter, map actions to subtype
559extension_action_subtype = {
560 # version 1.0
561 of_g.VERSION_1_0:dict( # Version 1.0 extensions
562 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700563 },
564 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700565 }
566 ),
567 of_g.VERSION_1_1:dict( # Version 1.0 extensions
568 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700569 },
570 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700571 }
572 ),
573 of_g.VERSION_1_2:dict( # Version 1.0 extensions
574 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700575 },
576 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700577 }
578 ),
579 of_g.VERSION_1_3:dict( # Version 1.0 extensions
580 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700581 },
582 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700583 }
584 ),
585}
586
587# Set to empty dict if no extension actions defined
588# Per OF Version, per experimenter, map actions to subtype
589extension_action_id_subtype = {
590 # version 1.0
591 of_g.VERSION_1_0:dict(),
592 of_g.VERSION_1_1:dict(),
593 of_g.VERSION_1_2:dict(),
594 of_g.VERSION_1_3:dict( # Version 1.3 extensions
595 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700596 },
597 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700598 }
599 ),
600}
601
602# Set to empty dict if no extension instructions defined
Rich Laneef7b9942013-11-18 16:29:28 -0800603extension_instruction_subtype = {
604 # version 1.0
605 of_g.VERSION_1_0:dict(),
606 of_g.VERSION_1_1:dict(),
607 of_g.VERSION_1_2:dict(),
608 of_g.VERSION_1_3:dict(
609 bsn = { # of_instruction_bsn_
610 },
611 nicira = { # of_instruction_nicira_
612 }
613 ),
614}
Rich Lanea06d0c32013-03-25 08:52:03 -0700615
616# Set to empty dict if no extension instructions defined
617extension_queue_prop_subtype = {}
618
619# Set to empty dict if no extension instructions defined
620extension_table_feature_prop_subtype = {}
621
622extension_objects = [
623 extension_message_subtype,
624 extension_action_subtype,
625 extension_action_id_subtype,
626 extension_instruction_subtype,
627 extension_queue_prop_subtype,
628 extension_table_feature_prop_subtype
629]
630
631################################################################
632# These are extension type generic (for messages, actions...)
633################################################################
634
635def extension_to_experimenter_name(cls):
636 """
637 Return the name of the experimenter if class is an
638 extension, else None
639
640 This is brute force; we search all extension data for a match
641 """
Andreas Wundsam53256162013-05-02 14:05:53 -0700642
Rich Lanea06d0c32013-03-25 08:52:03 -0700643 for ext_obj in extension_objects:
644 for version, exp_list in ext_obj.items():
645 for exp_name, classes in exp_list.items():
646 if cls in classes:
647 return exp_name
648 return None
649
650def extension_to_experimenter_id(cls):
651 """
652 Return the ID of the experimenter if class is an
653 extension, else None
654 """
655 exp_name = extension_to_experimenter_name(cls)
656 if exp_name:
657 return of_g.experimenter_name_to_id[exp_name]
658 return None
659
660def extension_to_experimenter_macro_name(cls):
661 """
662 Return the "macro name" of the ID of the experimenter if class is an
663 extension, else None
664 """
665 exp_name = extension_to_experimenter_name(cls)
666 if exp_name:
667 return "OF_EXPERIMENTER_ID_" + exp_name.upper()
668 return None
669
670def extension_to_subtype(cls, version):
671 """
672 Generic across all extension objects, return subtype identifier
673 """
674 for ext_obj in extension_objects:
675 for version, exp_list in ext_obj.items():
676 for exp_name, classes in exp_list.items():
677 if cls in classes:
678 return classes[cls]
679
680def class_is_extension(cls, version):
681 """
682 Return True if class, version is recognized as an extension
683 of any type (message, action....)
684
685 Accepts of_g.OF_VERSION_ANY
686 """
687
688 for ext_obj in extension_objects:
689 if cls_is_ext_obj(cls, version, ext_obj):
690 return True
691
692 return False
693
694# Internal
695def cls_is_ext_obj(cls, version, ext_obj):
696 """
697 @brief Return True if cls in an extension of type ext_obj
698 @param cls The class to check
699 @param version The version to check
700 @param ext_obj The extension object dictionary (messages, actions...)
701
702 Accepts of_g.VERSION_ANY
703 """
704
705 # Call with each version if "any" is passed
706 if version == of_g.VERSION_ANY:
707 for v in of_g.of_version_range:
708 if cls_is_ext_obj(cls, v, ext_obj):
709 return True
710 else: # Version specified
711 if version in ext_obj:
712 for exp, subtype_vals in ext_obj[version].items():
713 if cls in subtype_vals:
714 return True
715
716 return False
Andreas Wundsam53256162013-05-02 14:05:53 -0700717
Rich Lanea06d0c32013-03-25 08:52:03 -0700718################################################################
719# These are extension message specific
720################################################################
721
722def message_is_extension(cls, version):
723 """
724 Return True if cls, version is recognized as an extension
725 This is brute force, searching records for a match
726 """
727 return cls_is_ext_obj(cls, version, extension_message_subtype)
728
729def extension_message_to_subtype(cls, version):
730 """
731 Return the subtype of the experimenter message if the class is an
732 extension, else None
733 """
734 if version in extension_message_subtype:
735 for exp, classes in extension_message_subtype[version].items():
736 for ext_class, subtype in classes.items():
737 if cls == ext_class:
738 return subtype
739 return None
740
741################################################################
742# These are extension action specific
743################################################################
744
745def action_is_extension(cls, version):
746 """
747 Return True if cls, version is recognized as an action extension
748 This is brute force, searching records for a match
749 """
750 return cls_is_ext_obj(cls, version, extension_action_subtype)
751
752def extension_action_to_subtype(cls, version):
753 """
754 Return the ID of the action subtype (for its experimenteer)
755 if class is an action extension, else None
756 """
757 if version in extension_action_subtype:
758 for exp, classes in extension_action_subtype[version].items():
759 if cls in classes:
760 return classes[cls]
761
762 return None
763
764################################################################
765# These are extension action specific
766################################################################
767
768def action_id_is_extension(cls, version):
769 """
770 Return True if cls, version is recognized as an action ID extension
771 This is brute force, searching records for a match
772 """
773 if version not in [of_g.VERSION_1_3]: # Action IDs only 1.3
774 return False
775 return cls_is_ext_obj(cls, version, extension_action_id_subtype)
776
777def extension_action_id_to_subtype(cls, version):
778 """
779 Return the ID of the action ID subtype (for its experimenteer)
780 if class is an action ID extension, else None
781 """
782 if version in extension_action_id_subtype:
783 for exp, classes in extension_action_id_subtype[version].items():
784 if cls in classes:
785 return classes[cls]
786
787 return None
788
789################################################################
790# These are extension instruction specific
791################################################################
792
793def instruction_is_extension(cls, version):
794 """
795 Return True if cls, version is recognized as an instruction extension
796 This is brute force, searching records for a match
797 """
798 return cls_is_ext_obj(cls, version, extension_instruction_subtype)
799
800################################################################
801# These are extension queue_prop specific
802################################################################
803
804def queue_prop_is_extension(cls, version):
805 """
806 Return True if cls, version is recognized as an instruction extension
807 This is brute force, searching records for a match
808 """
809 return cls_is_ext_obj(cls, version, extension_queue_prop_subtype)
810
811################################################################
812# These are extension table_feature_prop specific
813################################################################
814
815def table_feature_prop_is_extension(cls, version):
816 """
817 Return True if cls, version is recognized as an instruction extension
818 This is brute force, searching records for a match
819 """
820 return cls_is_ext_obj(cls, version,
821 extension_table_feature_prop_subtype)