blob: cf88e35525bf547f69d9c9e189479c44db22e0ba [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 Lane353a79f2013-11-13 10:39:56 -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"]:
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",
Rich Lanea06d0c32013-03-25 08:52:03 -0700459]
460
461stats_request_list = [
462 "of_aggregate_stats_request",
463 "of_desc_stats_request",
464 "of_experimenter_stats_request",
465 "of_flow_stats_request",
466 "of_group_stats_request",
467 "of_group_desc_stats_request",
468 "of_group_features_stats_request",
469 "of_meter_stats_request",
470 "of_meter_config_stats_request",
471 "of_meter_features_stats_request",
472 "of_port_stats_request",
473 "of_port_desc_stats_request",
474 "of_queue_stats_request",
475 "of_table_stats_request",
Rich Lane353a79f2013-11-13 10:39:56 -0800476 "of_table_features_stats_request",
477 "of_bsn_stats_request",
478 "of_bsn_lacp_stats_request",
Rich Lanea06d0c32013-03-25 08:52:03 -0700479]
480
481flow_mod_list = [
482 "of_flow_add",
483 "of_flow_modify",
484 "of_flow_modify_strict",
485 "of_flow_delete",
486 "of_flow_delete_strict"
487]
488
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700489error_msg_list = [
490 "of_hello_failed_error_msg",
491 "of_bad_request_error_msg",
492 "of_bad_action_error_msg",
493 "of_bad_instruction_error_msg",
494 "of_bad_match_error_msg",
495 "of_flow_mod_failed_error_msg",
496 "of_group_mod_failed_error_msg",
497 "of_port_mod_failed_error_msg",
498 "of_table_mod_failed_error_msg",
499 "of_queue_op_failed_error_msg",
500 "of_switch_config_failed_error_msg",
501 "of_role_request_failed_error_msg",
502 "of_meter_mod_failed_error_msg",
503 "of_table_features_failed_error_msg",
504 "of_experimenter_error_msg"
505]
506
Rich Lanea06d0c32013-03-25 08:52:03 -0700507def sub_class_map(base_type, version):
508 """
509 Returns an iterable object giving the instance nameys and subclass types
510 for the base_type, version values
511 """
512 rv = []
513 if base_type not in inheritance_map:
514 return rv
515
516 for instance in inheritance_map[base_type]:
517 subcls = loxi_utils.instance_to_class(instance, base_type)
518 if not loxi_utils.class_in_version(subcls, version):
519 continue
520 rv.append((instance, subcls))
521
522 return rv
523
524################################################################
525#
526# Extension related data and functions
527#
528################################################################
529
530# Per OF Version, per experimenter, map exp msg type (subtype) to object IDs
531# @fixme Generate defines for OF_<exp>_SUBTYPE_<msg> for the values below?
532extension_message_subtype = {
533 # version 1.0
534 of_g.VERSION_1_0: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 nicira = { # Nicira extensions, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700538 },
539 ),
540 of_g.VERSION_1_1:dict( # Version 1.0 extensions
541 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700542 },
543 ),
544 of_g.VERSION_1_2:dict( # Version 1.0 extensions
545 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700546 },
547 ),
548 of_g.VERSION_1_3:dict( # Version 1.0 extensions
549 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700550 },
551 ),
552}
553
554# Set to empty dict if no extension actions defined
555# Per OF Version, per experimenter, map actions to subtype
556extension_action_subtype = {
557 # version 1.0
558 of_g.VERSION_1_0: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_1: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_2: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 of_g.VERSION_1_3:dict( # Version 1.0 extensions
577 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700578 },
579 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700580 }
581 ),
582}
583
584# Set to empty dict if no extension actions defined
585# Per OF Version, per experimenter, map actions to subtype
586extension_action_id_subtype = {
587 # version 1.0
588 of_g.VERSION_1_0:dict(),
589 of_g.VERSION_1_1:dict(),
590 of_g.VERSION_1_2:dict(),
591 of_g.VERSION_1_3:dict( # Version 1.3 extensions
592 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700593 },
594 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700595 }
596 ),
597}
598
599# Set to empty dict if no extension instructions defined
600extension_instruction_subtype = {}
601
602# Set to empty dict if no extension instructions defined
603extension_queue_prop_subtype = {}
604
605# Set to empty dict if no extension instructions defined
606extension_table_feature_prop_subtype = {}
607
608extension_objects = [
609 extension_message_subtype,
610 extension_action_subtype,
611 extension_action_id_subtype,
612 extension_instruction_subtype,
613 extension_queue_prop_subtype,
614 extension_table_feature_prop_subtype
615]
616
617################################################################
618# These are extension type generic (for messages, actions...)
619################################################################
620
621def extension_to_experimenter_name(cls):
622 """
623 Return the name of the experimenter if class is an
624 extension, else None
625
626 This is brute force; we search all extension data for a match
627 """
Andreas Wundsam53256162013-05-02 14:05:53 -0700628
Rich Lanea06d0c32013-03-25 08:52:03 -0700629 for ext_obj in extension_objects:
630 for version, exp_list in ext_obj.items():
631 for exp_name, classes in exp_list.items():
632 if cls in classes:
633 return exp_name
634 return None
635
636def extension_to_experimenter_id(cls):
637 """
638 Return the ID of the experimenter if class is an
639 extension, else None
640 """
641 exp_name = extension_to_experimenter_name(cls)
642 if exp_name:
643 return of_g.experimenter_name_to_id[exp_name]
644 return None
645
646def extension_to_experimenter_macro_name(cls):
647 """
648 Return the "macro name" of the ID of the experimenter if class is an
649 extension, else None
650 """
651 exp_name = extension_to_experimenter_name(cls)
652 if exp_name:
653 return "OF_EXPERIMENTER_ID_" + exp_name.upper()
654 return None
655
656def extension_to_subtype(cls, version):
657 """
658 Generic across all extension objects, return subtype identifier
659 """
660 for ext_obj in extension_objects:
661 for version, exp_list in ext_obj.items():
662 for exp_name, classes in exp_list.items():
663 if cls in classes:
664 return classes[cls]
665
666def class_is_extension(cls, version):
667 """
668 Return True if class, version is recognized as an extension
669 of any type (message, action....)
670
671 Accepts of_g.OF_VERSION_ANY
672 """
673
674 for ext_obj in extension_objects:
675 if cls_is_ext_obj(cls, version, ext_obj):
676 return True
677
678 return False
679
680# Internal
681def cls_is_ext_obj(cls, version, ext_obj):
682 """
683 @brief Return True if cls in an extension of type ext_obj
684 @param cls The class to check
685 @param version The version to check
686 @param ext_obj The extension object dictionary (messages, actions...)
687
688 Accepts of_g.VERSION_ANY
689 """
690
691 # Call with each version if "any" is passed
692 if version == of_g.VERSION_ANY:
693 for v in of_g.of_version_range:
694 if cls_is_ext_obj(cls, v, ext_obj):
695 return True
696 else: # Version specified
697 if version in ext_obj:
698 for exp, subtype_vals in ext_obj[version].items():
699 if cls in subtype_vals:
700 return True
701
702 return False
Andreas Wundsam53256162013-05-02 14:05:53 -0700703
Rich Lanea06d0c32013-03-25 08:52:03 -0700704################################################################
705# These are extension message specific
706################################################################
707
708def message_is_extension(cls, version):
709 """
710 Return True if cls, version is recognized as an extension
711 This is brute force, searching records for a match
712 """
713 return cls_is_ext_obj(cls, version, extension_message_subtype)
714
715def extension_message_to_subtype(cls, version):
716 """
717 Return the subtype of the experimenter message if the class is an
718 extension, else None
719 """
720 if version in extension_message_subtype:
721 for exp, classes in extension_message_subtype[version].items():
722 for ext_class, subtype in classes.items():
723 if cls == ext_class:
724 return subtype
725 return None
726
727################################################################
728# These are extension action specific
729################################################################
730
731def action_is_extension(cls, version):
732 """
733 Return True if cls, version is recognized as an action extension
734 This is brute force, searching records for a match
735 """
736 return cls_is_ext_obj(cls, version, extension_action_subtype)
737
738def extension_action_to_subtype(cls, version):
739 """
740 Return the ID of the action subtype (for its experimenteer)
741 if class is an action extension, else None
742 """
743 if version in extension_action_subtype:
744 for exp, classes in extension_action_subtype[version].items():
745 if cls in classes:
746 return classes[cls]
747
748 return None
749
750################################################################
751# These are extension action specific
752################################################################
753
754def action_id_is_extension(cls, version):
755 """
756 Return True if cls, version is recognized as an action ID extension
757 This is brute force, searching records for a match
758 """
759 if version not in [of_g.VERSION_1_3]: # Action IDs only 1.3
760 return False
761 return cls_is_ext_obj(cls, version, extension_action_id_subtype)
762
763def extension_action_id_to_subtype(cls, version):
764 """
765 Return the ID of the action ID subtype (for its experimenteer)
766 if class is an action ID extension, else None
767 """
768 if version in extension_action_id_subtype:
769 for exp, classes in extension_action_id_subtype[version].items():
770 if cls in classes:
771 return classes[cls]
772
773 return None
774
775################################################################
776# These are extension instruction specific
777################################################################
778
779def instruction_is_extension(cls, version):
780 """
781 Return True if cls, version is recognized as an instruction extension
782 This is brute force, searching records for a match
783 """
784 return cls_is_ext_obj(cls, version, extension_instruction_subtype)
785
786################################################################
787# These are extension queue_prop specific
788################################################################
789
790def queue_prop_is_extension(cls, version):
791 """
792 Return True if cls, version is recognized as an instruction extension
793 This is brute force, searching records for a match
794 """
795 return cls_is_ext_obj(cls, version, extension_queue_prop_subtype)
796
797################################################################
798# These are extension table_feature_prop specific
799################################################################
800
801def table_feature_prop_is_extension(cls, version):
802 """
803 Return True if cls, version is recognized as an instruction extension
804 This is brute force, searching records for a match
805 """
806 return cls_is_ext_obj(cls, version,
807 extension_table_feature_prop_subtype)