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