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