blob: e709b70b4da1a541c21d09dff639afb257d7e766 [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 Lane4def6972013-12-09 17:44:43 -080063instruction_id_types = {
64 of_g.VERSION_1_0:dict(),
65 of_g.VERSION_1_1:dict(),
66 of_g.VERSION_1_2:dict(),
67 of_g.VERSION_1_3:dict()
68 }
Rich Lanea06d0c32013-03-25 08:52:03 -070069
Rich Lanea06d0c32013-03-25 08:52:03 -070070action_types = {
Rich Lane4db4d042013-05-13 18:13:48 -070071 of_g.VERSION_1_0:dict(),
72 of_g.VERSION_1_1:dict(),
73 of_g.VERSION_1_2:dict(),
Rich Lane4def6972013-12-09 17:44:43 -080074 of_g.VERSION_1_3:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -070075 }
76
77action_id_types = {
Rich Lanea06d0c32013-03-25 08:52:03 -070078 of_g.VERSION_1_0:dict(),
79 of_g.VERSION_1_1:dict(),
80 of_g.VERSION_1_2:dict(),
Rich Lane4def6972013-12-09 17:44:43 -080081 of_g.VERSION_1_3:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -070082 }
83
84queue_prop_types = {
Rich Lane4db4d042013-05-13 18:13:48 -070085 of_g.VERSION_1_0:dict(),
86 of_g.VERSION_1_1:dict(),
87 of_g.VERSION_1_2:dict(),
88 of_g.VERSION_1_3:dict()
Rich Lanea06d0c32013-03-25 08:52:03 -070089 }
90
Dan Talaycoc0e802e2013-05-18 23:52:39 -070091bsn_vport_types = {
92 # version 1.0
93 of_g.VERSION_1_0:dict(
94 q_in_q = 0,
95 ),
96 # version 1.1
97 of_g.VERSION_1_1:dict(
98 q_in_q = 0,
99 ),
100 # version 1.2
101 of_g.VERSION_1_2:dict(
102 q_in_q = 0,
103 ),
104 # version 1.3
105 of_g.VERSION_1_3:dict(
106 q_in_q = 0,
107 )
108 }
109
Rich Lanea06d0c32013-03-25 08:52:03 -0700110oxm_types = {
Rich Lanea06d0c32013-03-25 08:52:03 -0700111 of_g.VERSION_1_0:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700112 of_g.VERSION_1_1:dict(),
Rich Lane4db4d042013-05-13 18:13:48 -0700113 of_g.VERSION_1_2:dict(),
114 of_g.VERSION_1_3:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700115 }
116
117hello_elem_types = {
Rich Lanea06d0c32013-03-25 08:52:03 -0700118 of_g.VERSION_1_0:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700119 of_g.VERSION_1_1:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700120 of_g.VERSION_1_2:dict(),
Rich Lane4db4d042013-05-13 18:13:48 -0700121 of_g.VERSION_1_3:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700122 }
123
124table_feature_prop_types = {
Rich Lanea06d0c32013-03-25 08:52:03 -0700125 of_g.VERSION_1_0:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700126 of_g.VERSION_1_1:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700127 of_g.VERSION_1_2:dict(),
Rich Lane4db4d042013-05-13 18:13:48 -0700128 of_g.VERSION_1_3:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700129 }
130
131meter_band_types = {
Rich Lanea06d0c32013-03-25 08:52:03 -0700132 of_g.VERSION_1_0:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700133 of_g.VERSION_1_1:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700134 of_g.VERSION_1_2:dict(),
Rich Lane4db4d042013-05-13 18:13:48 -0700135 of_g.VERSION_1_3:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700136 }
137
138# All inheritance data for non-messages
139inheritance_data = dict(
140 of_instruction = instruction_types,
Rich Lane4def6972013-12-09 17:44:43 -0800141 of_instruction_id = instruction_id_types,
Rich Lanea06d0c32013-03-25 08:52:03 -0700142 of_action = action_types,
143 of_action_id = action_id_types,
144 of_oxm = oxm_types,
145 of_queue_prop = queue_prop_types,
146 of_hello_elem = hello_elem_types,
147 of_table_feature_prop = table_feature_prop_types,
Dan Talaycoc0e802e2013-05-18 23:52:39 -0700148 of_meter_band = meter_band_types,
149 # BSN specific inheritance extensions
150 of_bsn_vport = bsn_vport_types
Rich Lanea06d0c32013-03-25 08:52:03 -0700151 )
152
Rich Lanea06d0c32013-03-25 08:52:03 -0700153def class_is_virtual(cls):
154 """
155 Returns True if cls is a virtual class
156 """
157 if cls in inheritance_map:
158 return True
159 if cls.find("header") > 0:
160 return True
161 if loxi_utils.class_is_list(cls):
162 return True
Rich Lane488b3c52013-06-21 18:11:02 -0700163 # TODO get this from the input file when we have virtual class syntax
Rich Lanee3113672013-12-06 17:09:57 -0800164 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", "of_group_mod"]:
Rich Lane488b3c52013-06-21 18:11:02 -0700165 return True
Rich Lanea06d0c32013-03-25 08:52:03 -0700166 return False
167
168################################################################
169#
170# These are message types
171#
172################################################################
173
Rich Lanedf847e32013-05-29 16:57:30 -0700174# The hardcoded message types are for inheritance parents
Rich Lanea06d0c32013-03-25 08:52:03 -0700175message_types = {
176 # version 1.0
177 of_g.VERSION_1_0:dict(
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700178 error_msg = 1,
Rich Lanedf847e32013-05-29 16:57:30 -0700179 experimenter = 4,
Rich Lanea06d0c32013-03-25 08:52:03 -0700180 flow_mod = 14,
Rich Lanea06d0c32013-03-25 08:52:03 -0700181 stats_request = 16,
182 stats_reply = 17,
Rich Lanea06d0c32013-03-25 08:52:03 -0700183 ),
184
185 # version 1.1
186 of_g.VERSION_1_1:dict(
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700187 error_msg = 1,
Rich Lanedf847e32013-05-29 16:57:30 -0700188 experimenter = 4,
Rich Lanea06d0c32013-03-25 08:52:03 -0700189 flow_mod = 14,
Rich Lanee3113672013-12-06 17:09:57 -0800190 group_mod = 15,
Rich Lanea06d0c32013-03-25 08:52:03 -0700191 stats_request = 18,
192 stats_reply = 19,
Rich Lanea06d0c32013-03-25 08:52:03 -0700193 ),
194
195 # version 1.2
196 of_g.VERSION_1_2:dict(
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700197 error_msg = 1,
Rich Lanedf847e32013-05-29 16:57:30 -0700198 experimenter = 4,
Rich Lanea06d0c32013-03-25 08:52:03 -0700199 flow_mod = 14,
Rich Lanee3113672013-12-06 17:09:57 -0800200 group_mod = 15,
Rich Lanea06d0c32013-03-25 08:52:03 -0700201 stats_request = 18,
202 stats_reply = 19,
Rich Lanea06d0c32013-03-25 08:52:03 -0700203 ),
204
205 # version 1.3
206 of_g.VERSION_1_3:dict(
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700207 error_msg = 1,
Rich Lanedf847e32013-05-29 16:57:30 -0700208 experimenter = 4,
Rich Lanea06d0c32013-03-25 08:52:03 -0700209 flow_mod = 14,
Rich Lanee3113672013-12-06 17:09:57 -0800210 group_mod = 15,
Rich Lanea06d0c32013-03-25 08:52:03 -0700211 stats_request = 18, # FIXME Multipart
212 stats_reply = 19,
Rich Lanea06d0c32013-03-25 08:52:03 -0700213 )
214 }
215
216################################################################
217#
218# These are other objects that have a notion of type but are
219# not (yet) promoted to objects with inheritance
220#
221################################################################
222
223stats_types = {
224 # version 1.0
225 of_g.VERSION_1_0:dict(
226 desc = 0,
227 flow = 1,
228 aggregate = 2,
229 table = 3,
230 port = 4,
231 queue = 5,
232 experimenter = 0xffff
233 ),
234
235 # version 1.1
236 of_g.VERSION_1_1:dict(
237 desc = 0,
238 flow = 1,
239 aggregate = 2,
240 table = 3,
241 port = 4,
242 queue = 5,
243 group = 6,
244 group_desc = 7,
245 experimenter = 0xffff
246 ),
247
248 # version 1.2
249 of_g.VERSION_1_2:dict(
250 desc = 0,
251 flow = 1,
252 aggregate = 2,
253 table = 3,
254 port = 4,
255 queue = 5,
256 group = 6,
257 group_desc = 7,
258 group_features = 8,
259 experimenter = 0xffff
260 ),
261
262 # version 1.3
263 of_g.VERSION_1_3:dict(
264 desc = 0,
265 flow = 1,
266 aggregate = 2,
267 table = 3,
268 port = 4,
269 queue = 5,
270 group = 6,
271 group_desc = 7,
272 group_features = 8,
273 meter = 9,
274 meter_config = 10,
275 meter_features = 11,
276 table_features = 12,
277 port_desc = 13,
Rich Lane353a79f2013-11-13 10:39:56 -0800278 experimenter = 0xffff,
Wilson Ng45386fb2013-12-03 13:46:42 -0800279 bsn_lacp = 0xffff,
xinwu358e6162013-12-04 16:49:48 -0800280 bsn_switch_pipeline = 0xffff,
281 bsn_port_counter = 0xffff,
282 bsn_vlan_counter = 0xffff
Rich Lanea06d0c32013-03-25 08:52:03 -0700283 )
284 }
285
286common_flow_mod_types = dict(
287 add = 0,
288 modify = 1,
289 modify_strict = 2,
290 delete = 3,
291 delete_strict = 4
292 )
293
294flow_mod_types = {
295 # version 1.0
296 of_g.VERSION_1_0:common_flow_mod_types,
297 of_g.VERSION_1_1:common_flow_mod_types,
298 of_g.VERSION_1_2:common_flow_mod_types,
299 of_g.VERSION_1_3:common_flow_mod_types
300 }
301
302# These do not translate to objects (yet)
303error_types = {
304 # version 1.0
305 of_g.VERSION_1_0:dict(
306 hello_failed = 0,
307 bad_request = 1,
308 bad_action = 2,
309 flow_mod_failed = 3,
310 port_mod_failed = 4,
311 queue_op_failed = 5
312 ),
313
314 # version 1.1
315 of_g.VERSION_1_1:dict(
316 hello_failed = 0,
317 bad_request = 1,
318 bad_action = 2,
319 bad_instruction = 3,
320 bad_match = 4,
321 flow_mod_failed = 5,
322 group_mod_failed = 6,
323 port_mod_failed = 7,
324 table_mod_failed = 8,
325 queue_op_failed = 9,
326 switch_config_failed = 10
327 ),
328
329 # version 1.2
330 of_g.VERSION_1_2:dict(
331 hello_failed = 0,
332 bad_request = 1,
333 bad_action = 2,
334 bad_instruction = 3,
335 bad_match = 4,
336 flow_mod_failed = 5,
337 group_mod_failed = 6,
338 port_mod_failed = 7,
339 table_mod_failed = 8,
340 queue_op_failed = 9,
341 switch_config_failed = 10,
342 role_request_failed = 11,
343 experimenter = 0xffff
344 ),
345
346 # version 1.3
347 of_g.VERSION_1_3:dict(
348 hello_failed = 0,
349 bad_request = 1,
350 bad_action = 2,
351 bad_instruction = 3,
352 bad_match = 4,
353 flow_mod_failed = 5,
354 group_mod_failed = 6,
355 port_mod_failed = 7,
356 table_mod_failed = 8,
357 queue_op_failed = 9,
358 switch_config_failed = 10,
359 role_request_failed = 11,
360 meter_mod_failed = 12,
361 table_features_failed= 13,
362 experimenter = 0xffff
363 )
364 }
365
Rich Lanee3113672013-12-06 17:09:57 -0800366group_mod_types = {
367 # version 1.0
368 of_g.VERSION_1_0:dict(),
369
370 # version 1.1
371 of_g.VERSION_1_1:dict(
372 add = 0,
373 modify = 1,
374 delete = 2
375 ),
376
377 # version 1.2
378 of_g.VERSION_1_2:dict(
379 add = 0,
380 modify = 1,
381 delete = 2
382 ),
383
384 # version 1.3
385 of_g.VERSION_1_3:dict(
386 add = 0,
387 modify = 1,
388 delete = 2
389 )
390 }
391
Rich Lanea06d0c32013-03-25 08:52:03 -0700392##
393# These are the objects whose length is specified by an external
394# reference, specifically another data member in the class.
Andreas Wundsam53256162013-05-02 14:05:53 -0700395#
Rich Lanea06d0c32013-03-25 08:52:03 -0700396#external_length_spec = {
397# ("of_packet_out", "actions", OF_VERSION_1_0) : "actions_len",
398# ("of_packet_out", "actions", OF_VERSION_1_1) : "actions_len",
399# ("of_packet_out", "actions", OF_VERSION_1_2) : "actions_len",
400# ("of_packet_out", "actions", OF_VERSION_1_3) : "actions_len"
401#}
402
403
404################################################################
405#
Andreas Wundsam53256162013-05-02 14:05:53 -0700406# type_val is the primary data structure that maps an
Rich Lanea06d0c32013-03-25 08:52:03 -0700407# (class_name, version) pair to the wire data type value
408#
409################################################################
410
411type_val = dict()
Rich Lane6bb28dd2013-05-13 15:19:14 -0700412inheritance_map = dict()
Rich Lanea06d0c32013-03-25 08:52:03 -0700413
Rich Lane6bb28dd2013-05-13 15:19:14 -0700414def generate_maps():
415 for parent, versioned in inheritance_data.items():
416 inheritance_map[parent] = set()
417 for ver, subclasses in versioned.items():
418 for subcls in subclasses:
419 inheritance_map[parent].add(subcls)
Rich Lanea06d0c32013-03-25 08:52:03 -0700420
Rich Lane6bb28dd2013-05-13 15:19:14 -0700421 for version, classes in message_types.items():
422 for cls in classes:
423 name = "of_" + cls
424 type_val[(name, version)] = classes[cls]
Rich Lanea06d0c32013-03-25 08:52:03 -0700425
Rich Lane6bb28dd2013-05-13 15:19:14 -0700426 for parent, versioned in inheritance_data.items():
427 for version, subclasses in versioned.items():
428 for subcls, value in subclasses.items():
429 name = parent + "_" + subcls
430 type_val[(name, version)] = value
431
432 # Special case OF-1.2 match type
Rich Lanea72c98e2013-07-12 16:40:06 -0700433 type_val[("of_match_v3", of_g.VERSION_1_2)] = 1
434 type_val[("of_match_v3", of_g.VERSION_1_3)] = 1
Rich Lanea06d0c32013-03-25 08:52:03 -0700435
436# Utility function
437def dict_to_array(d, m_val, def_val=-1):
438 """
439 Given a dictionary, d, with each value a small integer,
440 produce an array indexed by the integer whose value is the key.
441 @param d The dictionary
442 @param m_val Ignore values greater than m_val
443 @param def_val The default value (for indices not in range of d)
444 """
445
446 # Get the max value in range for hash
447 max_val = 0
448 for key in d:
449 if (d[key] > max_val) and (d[key] < m_val):
450 max_val = d[key]
451 ar = []
452 for x in range(0, max_val + 1):
453 ar.append(def_val)
454 for key in d:
455 if (d[key] < m_val):
456 ar[d[key]] = key
457 return ar
458
459def type_array_len(version_indexed, max_val):
460 """
461 Given versioned information about a type, calculate how long
462 the unified array should be.
463
Andreas Wundsam53256162013-05-02 14:05:53 -0700464 @param version_indexed A dict indexed by version. Each value is a
Rich Lanea06d0c32013-03-25 08:52:03 -0700465 dict indexed by a name and whose value is an integer
466 @param max_val Ignore values greater than this for length calcs
467 """
468 # First, find the max length of all arrays
469 arr_len = 0
470 for version, val_dict in version_indexed.items():
471 ar = dict_to_array(val_dict, max_val, invalid_type)
472 if arr_len < len(ar):
473 arr_len = len(ar)
474 return arr_len
475
476# FIXME: Need to move update for multipart messages
477
478stats_reply_list = [
479 "of_aggregate_stats_reply",
480 "of_desc_stats_reply",
481 "of_experimenter_stats_reply",
482 "of_flow_stats_reply",
483 "of_group_stats_reply",
484 "of_group_desc_stats_reply",
485 "of_group_features_stats_reply",
486 "of_meter_stats_reply",
487 "of_meter_config_stats_reply",
488 "of_meter_features_stats_reply",
489 "of_port_stats_reply",
490 "of_port_desc_stats_reply",
491 "of_queue_stats_reply",
492 "of_table_stats_reply",
Rich Lane353a79f2013-11-13 10:39:56 -0800493 "of_table_features_stats_reply",
494 "of_bsn_stats_reply",
495 "of_bsn_lacp_stats_reply",
Wilson Ng27e4beb2013-12-03 12:33:01 -0800496 "of_bsn_switch_pipeline_stats_reply",
xinwu358e6162013-12-04 16:49:48 -0800497 "of_bsn_port_counter_stats_reply",
498 "of_bsn_vlan_counter_stats_reply",
Rich Lanea06d0c32013-03-25 08:52:03 -0700499]
500
501stats_request_list = [
502 "of_aggregate_stats_request",
503 "of_desc_stats_request",
504 "of_experimenter_stats_request",
505 "of_flow_stats_request",
506 "of_group_stats_request",
507 "of_group_desc_stats_request",
508 "of_group_features_stats_request",
509 "of_meter_stats_request",
510 "of_meter_config_stats_request",
511 "of_meter_features_stats_request",
512 "of_port_stats_request",
513 "of_port_desc_stats_request",
514 "of_queue_stats_request",
515 "of_table_stats_request",
Rich Lane353a79f2013-11-13 10:39:56 -0800516 "of_table_features_stats_request",
517 "of_bsn_stats_request",
518 "of_bsn_lacp_stats_request",
Wilson Ng27e4beb2013-12-03 12:33:01 -0800519 "of_bsn_switch_pipeline_stats_request",
xinwu358e6162013-12-04 16:49:48 -0800520 "of_bsn_port_counter_stats_request",
521 "of_bsn_vlan_counter_stats_request",
Rich Lanea06d0c32013-03-25 08:52:03 -0700522]
523
524flow_mod_list = [
525 "of_flow_add",
526 "of_flow_modify",
527 "of_flow_modify_strict",
528 "of_flow_delete",
529 "of_flow_delete_strict"
530]
531
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700532error_msg_list = [
533 "of_hello_failed_error_msg",
534 "of_bad_request_error_msg",
535 "of_bad_action_error_msg",
536 "of_bad_instruction_error_msg",
537 "of_bad_match_error_msg",
538 "of_flow_mod_failed_error_msg",
539 "of_group_mod_failed_error_msg",
540 "of_port_mod_failed_error_msg",
541 "of_table_mod_failed_error_msg",
542 "of_queue_op_failed_error_msg",
543 "of_switch_config_failed_error_msg",
544 "of_role_request_failed_error_msg",
545 "of_meter_mod_failed_error_msg",
546 "of_table_features_failed_error_msg",
547 "of_experimenter_error_msg"
548]
549
Rich Lanee3113672013-12-06 17:09:57 -0800550group_mod_list = [
551 "of_group_add",
552 "of_group_modify",
553 "of_group_delete",
554]
555
Rich Lanea06d0c32013-03-25 08:52:03 -0700556def sub_class_map(base_type, version):
557 """
558 Returns an iterable object giving the instance nameys and subclass types
559 for the base_type, version values
560 """
561 rv = []
562 if base_type not in inheritance_map:
563 return rv
564
565 for instance in inheritance_map[base_type]:
566 subcls = loxi_utils.instance_to_class(instance, base_type)
567 if not loxi_utils.class_in_version(subcls, version):
568 continue
569 rv.append((instance, subcls))
570
571 return rv
572
573################################################################
574#
575# Extension related data and functions
576#
577################################################################
578
579# Per OF Version, per experimenter, map exp msg type (subtype) to object IDs
580# @fixme Generate defines for OF_<exp>_SUBTYPE_<msg> for the values below?
581extension_message_subtype = {
582 # version 1.0
583 of_g.VERSION_1_0:dict( # Version 1.0 extensions
584 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700585 },
586 nicira = { # Nicira extensions, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700587 },
588 ),
589 of_g.VERSION_1_1:dict( # Version 1.0 extensions
590 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700591 },
592 ),
593 of_g.VERSION_1_2:dict( # Version 1.0 extensions
594 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700595 },
596 ),
597 of_g.VERSION_1_3:dict( # Version 1.0 extensions
598 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700599 },
600 ),
601}
602
603# Set to empty dict if no extension actions defined
604# Per OF Version, per experimenter, map actions to subtype
605extension_action_subtype = {
606 # version 1.0
607 of_g.VERSION_1_0:dict( # Version 1.0 extensions
608 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700609 },
610 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700611 }
612 ),
613 of_g.VERSION_1_1:dict( # Version 1.0 extensions
614 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700615 },
616 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700617 }
618 ),
619 of_g.VERSION_1_2:dict( # Version 1.0 extensions
620 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700621 },
622 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700623 }
624 ),
625 of_g.VERSION_1_3:dict( # Version 1.0 extensions
626 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700627 },
628 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700629 }
630 ),
631}
632
633# Set to empty dict if no extension actions defined
634# Per OF Version, per experimenter, map actions to subtype
635extension_action_id_subtype = {
636 # version 1.0
637 of_g.VERSION_1_0:dict(),
638 of_g.VERSION_1_1:dict(),
639 of_g.VERSION_1_2:dict(),
640 of_g.VERSION_1_3:dict( # Version 1.3 extensions
641 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700642 },
643 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700644 }
645 ),
646}
647
648# Set to empty dict if no extension instructions defined
Rich Laneef7b9942013-11-18 16:29:28 -0800649extension_instruction_subtype = {
650 # version 1.0
651 of_g.VERSION_1_0:dict(),
652 of_g.VERSION_1_1:dict(),
653 of_g.VERSION_1_2:dict(),
654 of_g.VERSION_1_3:dict(
655 bsn = { # of_instruction_bsn_
656 },
657 nicira = { # of_instruction_nicira_
658 }
659 ),
660}
Rich Lanea06d0c32013-03-25 08:52:03 -0700661
662# Set to empty dict if no extension instructions defined
663extension_queue_prop_subtype = {}
664
665# Set to empty dict if no extension instructions defined
666extension_table_feature_prop_subtype = {}
667
668extension_objects = [
669 extension_message_subtype,
670 extension_action_subtype,
671 extension_action_id_subtype,
672 extension_instruction_subtype,
673 extension_queue_prop_subtype,
674 extension_table_feature_prop_subtype
675]
676
677################################################################
678# These are extension type generic (for messages, actions...)
679################################################################
680
681def extension_to_experimenter_name(cls):
682 """
683 Return the name of the experimenter if class is an
684 extension, else None
685
686 This is brute force; we search all extension data for a match
687 """
Andreas Wundsam53256162013-05-02 14:05:53 -0700688
Rich Lanea06d0c32013-03-25 08:52:03 -0700689 for ext_obj in extension_objects:
690 for version, exp_list in ext_obj.items():
691 for exp_name, classes in exp_list.items():
692 if cls in classes:
693 return exp_name
694 return None
695
696def extension_to_experimenter_id(cls):
697 """
698 Return the ID of the experimenter if class is an
699 extension, else None
700 """
701 exp_name = extension_to_experimenter_name(cls)
702 if exp_name:
703 return of_g.experimenter_name_to_id[exp_name]
704 return None
705
706def extension_to_experimenter_macro_name(cls):
707 """
708 Return the "macro name" of the ID of the experimenter if class is an
709 extension, else None
710 """
711 exp_name = extension_to_experimenter_name(cls)
712 if exp_name:
713 return "OF_EXPERIMENTER_ID_" + exp_name.upper()
714 return None
715
716def extension_to_subtype(cls, version):
717 """
718 Generic across all extension objects, return subtype identifier
719 """
720 for ext_obj in extension_objects:
721 for version, exp_list in ext_obj.items():
722 for exp_name, classes in exp_list.items():
723 if cls in classes:
724 return classes[cls]
725
726def class_is_extension(cls, version):
727 """
728 Return True if class, version is recognized as an extension
729 of any type (message, action....)
730
731 Accepts of_g.OF_VERSION_ANY
732 """
733
734 for ext_obj in extension_objects:
735 if cls_is_ext_obj(cls, version, ext_obj):
736 return True
737
738 return False
739
740# Internal
741def cls_is_ext_obj(cls, version, ext_obj):
742 """
743 @brief Return True if cls in an extension of type ext_obj
744 @param cls The class to check
745 @param version The version to check
746 @param ext_obj The extension object dictionary (messages, actions...)
747
748 Accepts of_g.VERSION_ANY
749 """
750
751 # Call with each version if "any" is passed
752 if version == of_g.VERSION_ANY:
753 for v in of_g.of_version_range:
754 if cls_is_ext_obj(cls, v, ext_obj):
755 return True
756 else: # Version specified
757 if version in ext_obj:
758 for exp, subtype_vals in ext_obj[version].items():
759 if cls in subtype_vals:
760 return True
761
762 return False
Andreas Wundsam53256162013-05-02 14:05:53 -0700763
Rich Lanea06d0c32013-03-25 08:52:03 -0700764################################################################
765# These are extension message specific
766################################################################
767
768def message_is_extension(cls, version):
769 """
770 Return True if cls, version is recognized as an extension
771 This is brute force, searching records for a match
772 """
773 return cls_is_ext_obj(cls, version, extension_message_subtype)
774
775def extension_message_to_subtype(cls, version):
776 """
777 Return the subtype of the experimenter message if the class is an
778 extension, else None
779 """
780 if version in extension_message_subtype:
781 for exp, classes in extension_message_subtype[version].items():
782 for ext_class, subtype in classes.items():
783 if cls == ext_class:
784 return subtype
785 return None
786
787################################################################
788# These are extension action specific
789################################################################
790
791def action_is_extension(cls, version):
792 """
793 Return True if cls, version is recognized as an action extension
794 This is brute force, searching records for a match
795 """
796 return cls_is_ext_obj(cls, version, extension_action_subtype)
797
798def extension_action_to_subtype(cls, version):
799 """
800 Return the ID of the action subtype (for its experimenteer)
801 if class is an action extension, else None
802 """
803 if version in extension_action_subtype:
804 for exp, classes in extension_action_subtype[version].items():
805 if cls in classes:
806 return classes[cls]
807
808 return None
809
810################################################################
811# These are extension action specific
812################################################################
813
814def action_id_is_extension(cls, version):
815 """
816 Return True if cls, version is recognized as an action ID extension
817 This is brute force, searching records for a match
818 """
819 if version not in [of_g.VERSION_1_3]: # Action IDs only 1.3
820 return False
821 return cls_is_ext_obj(cls, version, extension_action_id_subtype)
822
823def extension_action_id_to_subtype(cls, version):
824 """
825 Return the ID of the action ID subtype (for its experimenteer)
826 if class is an action ID extension, else None
827 """
828 if version in extension_action_id_subtype:
829 for exp, classes in extension_action_id_subtype[version].items():
830 if cls in classes:
831 return classes[cls]
832
833 return None
834
835################################################################
836# These are extension instruction specific
837################################################################
838
839def instruction_is_extension(cls, version):
840 """
841 Return True if cls, version is recognized as an instruction extension
842 This is brute force, searching records for a match
843 """
844 return cls_is_ext_obj(cls, version, extension_instruction_subtype)
845
846################################################################
847# These are extension queue_prop specific
848################################################################
849
850def queue_prop_is_extension(cls, version):
851 """
852 Return True if cls, version is recognized as an instruction extension
853 This is brute force, searching records for a match
854 """
855 return cls_is_ext_obj(cls, version, extension_queue_prop_subtype)
856
857################################################################
858# These are extension table_feature_prop specific
859################################################################
860
861def table_feature_prop_is_extension(cls, version):
862 """
863 Return True if cls, version is recognized as an instruction extension
864 This is brute force, searching records for a match
865 """
866 return cls_is_ext_obj(cls, version,
867 extension_table_feature_prop_subtype)