blob: f285a33b25c8dfe6c1df2c226f64afb3630d26f0 [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 Lane043a3d82013-12-10 10:57:30 -080041import loxi_globals
Rich Lanea06d0c32013-03-25 08:52:03 -070042
43invalid_type = "invalid_type"
44invalid_value = "0xeeee" # Note, as a string
45
46################################################################
47#
48# Define type data for inheritance classes:
49# instructions, actions, queue properties and OXM
50#
51# Messages are not in this group; they're treated specially for now
52#
53# These are indexed by wire protocol number
54#
55################################################################
56
57instruction_types = {
Rich Lanea06d0c32013-03-25 08:52:03 -070058 of_g.VERSION_1_0:dict(),
Rich Lane4db4d042013-05-13 18:13:48 -070059 of_g.VERSION_1_1:dict(),
60 of_g.VERSION_1_2:dict(),
61 of_g.VERSION_1_3:dict()
Rich Lanea06d0c32013-03-25 08:52:03 -070062 }
63
Rich Lane4def6972013-12-09 17:44:43 -080064instruction_id_types = {
65 of_g.VERSION_1_0:dict(),
66 of_g.VERSION_1_1:dict(),
67 of_g.VERSION_1_2:dict(),
68 of_g.VERSION_1_3:dict()
69 }
Rich Lanea06d0c32013-03-25 08:52:03 -070070
Rich Lanea06d0c32013-03-25 08:52:03 -070071action_types = {
Rich Lane4db4d042013-05-13 18:13:48 -070072 of_g.VERSION_1_0:dict(),
73 of_g.VERSION_1_1:dict(),
74 of_g.VERSION_1_2:dict(),
Rich Lane4def6972013-12-09 17:44:43 -080075 of_g.VERSION_1_3:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -070076 }
77
78action_id_types = {
Rich Lanea06d0c32013-03-25 08:52:03 -070079 of_g.VERSION_1_0:dict(),
80 of_g.VERSION_1_1:dict(),
81 of_g.VERSION_1_2:dict(),
Rich Lane4def6972013-12-09 17:44:43 -080082 of_g.VERSION_1_3:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -070083 }
84
85queue_prop_types = {
Rich Lane4db4d042013-05-13 18:13:48 -070086 of_g.VERSION_1_0:dict(),
87 of_g.VERSION_1_1:dict(),
88 of_g.VERSION_1_2:dict(),
89 of_g.VERSION_1_3:dict()
Rich Lanea06d0c32013-03-25 08:52:03 -070090 }
91
Dan Talaycoc0e802e2013-05-18 23:52:39 -070092bsn_vport_types = {
93 # version 1.0
94 of_g.VERSION_1_0:dict(
95 q_in_q = 0,
96 ),
97 # version 1.1
98 of_g.VERSION_1_1:dict(
99 q_in_q = 0,
100 ),
101 # version 1.2
102 of_g.VERSION_1_2:dict(
103 q_in_q = 0,
104 ),
105 # version 1.3
106 of_g.VERSION_1_3:dict(
107 q_in_q = 0,
108 )
109 }
110
Rich Lanea06d0c32013-03-25 08:52:03 -0700111oxm_types = {
Rich Lanea06d0c32013-03-25 08:52:03 -0700112 of_g.VERSION_1_0:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700113 of_g.VERSION_1_1:dict(),
Rich Lane4db4d042013-05-13 18:13:48 -0700114 of_g.VERSION_1_2:dict(),
115 of_g.VERSION_1_3:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700116 }
117
118hello_elem_types = {
Rich Lanea06d0c32013-03-25 08:52:03 -0700119 of_g.VERSION_1_0:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700120 of_g.VERSION_1_1:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700121 of_g.VERSION_1_2:dict(),
Rich Lane4db4d042013-05-13 18:13:48 -0700122 of_g.VERSION_1_3:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700123 }
124
125table_feature_prop_types = {
Rich Lanea06d0c32013-03-25 08:52:03 -0700126 of_g.VERSION_1_0:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700127 of_g.VERSION_1_1:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700128 of_g.VERSION_1_2:dict(),
Rich Lane4db4d042013-05-13 18:13:48 -0700129 of_g.VERSION_1_3:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700130 }
131
132meter_band_types = {
Rich Lanea06d0c32013-03-25 08:52:03 -0700133 of_g.VERSION_1_0:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700134 of_g.VERSION_1_1:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700135 of_g.VERSION_1_2:dict(),
Rich Lane4db4d042013-05-13 18:13:48 -0700136 of_g.VERSION_1_3:dict(),
Rich Lanea06d0c32013-03-25 08:52:03 -0700137 }
138
139# All inheritance data for non-messages
140inheritance_data = dict(
141 of_instruction = instruction_types,
Rich Lane4def6972013-12-09 17:44:43 -0800142 of_instruction_id = instruction_id_types,
Rich Lanea06d0c32013-03-25 08:52:03 -0700143 of_action = action_types,
144 of_action_id = action_id_types,
145 of_oxm = oxm_types,
146 of_queue_prop = queue_prop_types,
147 of_hello_elem = hello_elem_types,
148 of_table_feature_prop = table_feature_prop_types,
Dan Talaycoc0e802e2013-05-18 23:52:39 -0700149 of_meter_band = meter_band_types,
150 # BSN specific inheritance extensions
151 of_bsn_vport = bsn_vport_types
Rich Lanea06d0c32013-03-25 08:52:03 -0700152 )
153
Rich Lanea06d0c32013-03-25 08:52:03 -0700154def class_is_virtual(cls):
155 """
156 Returns True if cls is a virtual class
157 """
Rich Lanea06d0c32013-03-25 08:52:03 -0700158 if cls.find("header") > 0:
159 return True
160 if loxi_utils.class_is_list(cls):
161 return True
Rich Lane043a3d82013-12-10 10:57:30 -0800162 return loxi_globals.unified.class_by_name(cls).virtual
Rich Lanea06d0c32013-03-25 08:52:03 -0700163
164################################################################
165#
166# These are message types
167#
168################################################################
169
Rich Lanedf847e32013-05-29 16:57:30 -0700170# The hardcoded message types are for inheritance parents
Rich Lanea06d0c32013-03-25 08:52:03 -0700171message_types = {
172 # version 1.0
173 of_g.VERSION_1_0:dict(
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700174 error_msg = 1,
Rich Lanedf847e32013-05-29 16:57:30 -0700175 experimenter = 4,
Rich Lanea06d0c32013-03-25 08:52:03 -0700176 flow_mod = 14,
Rich Lanea06d0c32013-03-25 08:52:03 -0700177 stats_request = 16,
178 stats_reply = 17,
Rich Lanea06d0c32013-03-25 08:52:03 -0700179 ),
180
181 # version 1.1
182 of_g.VERSION_1_1:dict(
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700183 error_msg = 1,
Rich Lanedf847e32013-05-29 16:57:30 -0700184 experimenter = 4,
Rich Lanea06d0c32013-03-25 08:52:03 -0700185 flow_mod = 14,
Rich Lanee3113672013-12-06 17:09:57 -0800186 group_mod = 15,
Rich Lanea06d0c32013-03-25 08:52:03 -0700187 stats_request = 18,
188 stats_reply = 19,
Rich Lanea06d0c32013-03-25 08:52:03 -0700189 ),
190
191 # version 1.2
192 of_g.VERSION_1_2:dict(
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700193 error_msg = 1,
Rich Lanedf847e32013-05-29 16:57:30 -0700194 experimenter = 4,
Rich Lanea06d0c32013-03-25 08:52:03 -0700195 flow_mod = 14,
Rich Lanee3113672013-12-06 17:09:57 -0800196 group_mod = 15,
Rich Lanea06d0c32013-03-25 08:52:03 -0700197 stats_request = 18,
198 stats_reply = 19,
Rich Lanea06d0c32013-03-25 08:52:03 -0700199 ),
200
201 # version 1.3
202 of_g.VERSION_1_3:dict(
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700203 error_msg = 1,
Rich Lanedf847e32013-05-29 16:57:30 -0700204 experimenter = 4,
Rich Lanea06d0c32013-03-25 08:52:03 -0700205 flow_mod = 14,
Rich Lanee3113672013-12-06 17:09:57 -0800206 group_mod = 15,
Rich Lanea06d0c32013-03-25 08:52:03 -0700207 stats_request = 18, # FIXME Multipart
208 stats_reply = 19,
Rich Lanea06d0c32013-03-25 08:52:03 -0700209 )
210 }
211
212################################################################
213#
214# These are other objects that have a notion of type but are
215# not (yet) promoted to objects with inheritance
216#
217################################################################
218
219stats_types = {
220 # version 1.0
221 of_g.VERSION_1_0:dict(
222 desc = 0,
223 flow = 1,
224 aggregate = 2,
225 table = 3,
226 port = 4,
227 queue = 5,
228 experimenter = 0xffff
229 ),
230
231 # version 1.1
232 of_g.VERSION_1_1:dict(
233 desc = 0,
234 flow = 1,
235 aggregate = 2,
236 table = 3,
237 port = 4,
238 queue = 5,
239 group = 6,
240 group_desc = 7,
241 experimenter = 0xffff
242 ),
243
244 # version 1.2
245 of_g.VERSION_1_2:dict(
246 desc = 0,
247 flow = 1,
248 aggregate = 2,
249 table = 3,
250 port = 4,
251 queue = 5,
252 group = 6,
253 group_desc = 7,
254 group_features = 8,
255 experimenter = 0xffff
256 ),
257
258 # version 1.3
259 of_g.VERSION_1_3:dict(
260 desc = 0,
261 flow = 1,
262 aggregate = 2,
263 table = 3,
264 port = 4,
265 queue = 5,
266 group = 6,
267 group_desc = 7,
268 group_features = 8,
269 meter = 9,
270 meter_config = 10,
271 meter_features = 11,
272 table_features = 12,
273 port_desc = 13,
Rich Lane353a79f2013-11-13 10:39:56 -0800274 experimenter = 0xffff,
Wilson Ng45386fb2013-12-03 13:46:42 -0800275 bsn_lacp = 0xffff,
xinwu358e6162013-12-04 16:49:48 -0800276 bsn_switch_pipeline = 0xffff,
277 bsn_port_counter = 0xffff,
278 bsn_vlan_counter = 0xffff
Rich Lanea06d0c32013-03-25 08:52:03 -0700279 )
280 }
281
282common_flow_mod_types = dict(
283 add = 0,
284 modify = 1,
285 modify_strict = 2,
286 delete = 3,
287 delete_strict = 4
288 )
289
290flow_mod_types = {
291 # version 1.0
292 of_g.VERSION_1_0:common_flow_mod_types,
293 of_g.VERSION_1_1:common_flow_mod_types,
294 of_g.VERSION_1_2:common_flow_mod_types,
295 of_g.VERSION_1_3:common_flow_mod_types
296 }
297
298# These do not translate to objects (yet)
299error_types = {
300 # version 1.0
301 of_g.VERSION_1_0:dict(
302 hello_failed = 0,
303 bad_request = 1,
304 bad_action = 2,
305 flow_mod_failed = 3,
306 port_mod_failed = 4,
307 queue_op_failed = 5
308 ),
309
310 # version 1.1
311 of_g.VERSION_1_1:dict(
312 hello_failed = 0,
313 bad_request = 1,
314 bad_action = 2,
315 bad_instruction = 3,
316 bad_match = 4,
317 flow_mod_failed = 5,
318 group_mod_failed = 6,
319 port_mod_failed = 7,
320 table_mod_failed = 8,
321 queue_op_failed = 9,
322 switch_config_failed = 10
323 ),
324
325 # version 1.2
326 of_g.VERSION_1_2:dict(
327 hello_failed = 0,
328 bad_request = 1,
329 bad_action = 2,
330 bad_instruction = 3,
331 bad_match = 4,
332 flow_mod_failed = 5,
333 group_mod_failed = 6,
334 port_mod_failed = 7,
335 table_mod_failed = 8,
336 queue_op_failed = 9,
337 switch_config_failed = 10,
338 role_request_failed = 11,
339 experimenter = 0xffff
340 ),
341
342 # version 1.3
343 of_g.VERSION_1_3:dict(
344 hello_failed = 0,
345 bad_request = 1,
346 bad_action = 2,
347 bad_instruction = 3,
348 bad_match = 4,
349 flow_mod_failed = 5,
350 group_mod_failed = 6,
351 port_mod_failed = 7,
352 table_mod_failed = 8,
353 queue_op_failed = 9,
354 switch_config_failed = 10,
355 role_request_failed = 11,
356 meter_mod_failed = 12,
357 table_features_failed= 13,
358 experimenter = 0xffff
359 )
360 }
361
Rich Lanee3113672013-12-06 17:09:57 -0800362group_mod_types = {
363 # version 1.0
364 of_g.VERSION_1_0:dict(),
365
366 # version 1.1
367 of_g.VERSION_1_1:dict(
368 add = 0,
369 modify = 1,
370 delete = 2
371 ),
372
373 # version 1.2
374 of_g.VERSION_1_2:dict(
375 add = 0,
376 modify = 1,
377 delete = 2
378 ),
379
380 # version 1.3
381 of_g.VERSION_1_3:dict(
382 add = 0,
383 modify = 1,
384 delete = 2
385 )
386 }
387
Rich Lanea06d0c32013-03-25 08:52:03 -0700388##
389# These are the objects whose length is specified by an external
390# reference, specifically another data member in the class.
Andreas Wundsam53256162013-05-02 14:05:53 -0700391#
Rich Lanea06d0c32013-03-25 08:52:03 -0700392#external_length_spec = {
393# ("of_packet_out", "actions", OF_VERSION_1_0) : "actions_len",
394# ("of_packet_out", "actions", OF_VERSION_1_1) : "actions_len",
395# ("of_packet_out", "actions", OF_VERSION_1_2) : "actions_len",
396# ("of_packet_out", "actions", OF_VERSION_1_3) : "actions_len"
397#}
398
399
400################################################################
401#
Andreas Wundsam53256162013-05-02 14:05:53 -0700402# type_val is the primary data structure that maps an
Rich Lanea06d0c32013-03-25 08:52:03 -0700403# (class_name, version) pair to the wire data type value
404#
405################################################################
406
407type_val = dict()
Rich Lane6bb28dd2013-05-13 15:19:14 -0700408inheritance_map = dict()
Rich Lanea06d0c32013-03-25 08:52:03 -0700409
Rich Lane6bb28dd2013-05-13 15:19:14 -0700410def generate_maps():
411 for parent, versioned in inheritance_data.items():
412 inheritance_map[parent] = set()
413 for ver, subclasses in versioned.items():
414 for subcls in subclasses:
415 inheritance_map[parent].add(subcls)
Rich Lanea06d0c32013-03-25 08:52:03 -0700416
Rich Lane6bb28dd2013-05-13 15:19:14 -0700417 for version, classes in message_types.items():
418 for cls in classes:
419 name = "of_" + cls
420 type_val[(name, version)] = classes[cls]
Rich Lanea06d0c32013-03-25 08:52:03 -0700421
Rich Lane6bb28dd2013-05-13 15:19:14 -0700422 for parent, versioned in inheritance_data.items():
423 for version, subclasses in versioned.items():
424 for subcls, value in subclasses.items():
425 name = parent + "_" + subcls
426 type_val[(name, version)] = value
427
428 # Special case OF-1.2 match type
Rich Lanea72c98e2013-07-12 16:40:06 -0700429 type_val[("of_match_v3", of_g.VERSION_1_2)] = 1
430 type_val[("of_match_v3", of_g.VERSION_1_3)] = 1
Rich Lanea06d0c32013-03-25 08:52:03 -0700431
432# Utility function
433def dict_to_array(d, m_val, def_val=-1):
434 """
435 Given a dictionary, d, with each value a small integer,
436 produce an array indexed by the integer whose value is the key.
437 @param d The dictionary
438 @param m_val Ignore values greater than m_val
439 @param def_val The default value (for indices not in range of d)
440 """
441
442 # Get the max value in range for hash
443 max_val = 0
444 for key in d:
445 if (d[key] > max_val) and (d[key] < m_val):
446 max_val = d[key]
447 ar = []
448 for x in range(0, max_val + 1):
449 ar.append(def_val)
450 for key in d:
451 if (d[key] < m_val):
452 ar[d[key]] = key
453 return ar
454
455def type_array_len(version_indexed, max_val):
456 """
457 Given versioned information about a type, calculate how long
458 the unified array should be.
459
Andreas Wundsam53256162013-05-02 14:05:53 -0700460 @param version_indexed A dict indexed by version. Each value is a
Rich Lanea06d0c32013-03-25 08:52:03 -0700461 dict indexed by a name and whose value is an integer
462 @param max_val Ignore values greater than this for length calcs
463 """
464 # First, find the max length of all arrays
465 arr_len = 0
466 for version, val_dict in version_indexed.items():
467 ar = dict_to_array(val_dict, max_val, invalid_type)
468 if arr_len < len(ar):
469 arr_len = len(ar)
470 return arr_len
471
472# FIXME: Need to move update for multipart messages
473
474stats_reply_list = [
475 "of_aggregate_stats_reply",
476 "of_desc_stats_reply",
477 "of_experimenter_stats_reply",
478 "of_flow_stats_reply",
479 "of_group_stats_reply",
480 "of_group_desc_stats_reply",
481 "of_group_features_stats_reply",
482 "of_meter_stats_reply",
483 "of_meter_config_stats_reply",
484 "of_meter_features_stats_reply",
485 "of_port_stats_reply",
486 "of_port_desc_stats_reply",
487 "of_queue_stats_reply",
488 "of_table_stats_reply",
Rich Lane353a79f2013-11-13 10:39:56 -0800489 "of_table_features_stats_reply",
490 "of_bsn_stats_reply",
491 "of_bsn_lacp_stats_reply",
Wilson Ng27e4beb2013-12-03 12:33:01 -0800492 "of_bsn_switch_pipeline_stats_reply",
xinwu358e6162013-12-04 16:49:48 -0800493 "of_bsn_port_counter_stats_reply",
494 "of_bsn_vlan_counter_stats_reply",
Rich Lanea06d0c32013-03-25 08:52:03 -0700495]
496
497stats_request_list = [
498 "of_aggregate_stats_request",
499 "of_desc_stats_request",
500 "of_experimenter_stats_request",
501 "of_flow_stats_request",
502 "of_group_stats_request",
503 "of_group_desc_stats_request",
504 "of_group_features_stats_request",
505 "of_meter_stats_request",
506 "of_meter_config_stats_request",
507 "of_meter_features_stats_request",
508 "of_port_stats_request",
509 "of_port_desc_stats_request",
510 "of_queue_stats_request",
511 "of_table_stats_request",
Rich Lane353a79f2013-11-13 10:39:56 -0800512 "of_table_features_stats_request",
513 "of_bsn_stats_request",
514 "of_bsn_lacp_stats_request",
Wilson Ng27e4beb2013-12-03 12:33:01 -0800515 "of_bsn_switch_pipeline_stats_request",
xinwu358e6162013-12-04 16:49:48 -0800516 "of_bsn_port_counter_stats_request",
517 "of_bsn_vlan_counter_stats_request",
Rich Lanea06d0c32013-03-25 08:52:03 -0700518]
519
520flow_mod_list = [
521 "of_flow_add",
522 "of_flow_modify",
523 "of_flow_modify_strict",
524 "of_flow_delete",
525 "of_flow_delete_strict"
526]
527
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700528error_msg_list = [
529 "of_hello_failed_error_msg",
530 "of_bad_request_error_msg",
531 "of_bad_action_error_msg",
532 "of_bad_instruction_error_msg",
533 "of_bad_match_error_msg",
534 "of_flow_mod_failed_error_msg",
535 "of_group_mod_failed_error_msg",
536 "of_port_mod_failed_error_msg",
537 "of_table_mod_failed_error_msg",
538 "of_queue_op_failed_error_msg",
539 "of_switch_config_failed_error_msg",
540 "of_role_request_failed_error_msg",
541 "of_meter_mod_failed_error_msg",
542 "of_table_features_failed_error_msg",
543 "of_experimenter_error_msg"
544]
545
Rich Lanee3113672013-12-06 17:09:57 -0800546group_mod_list = [
547 "of_group_add",
548 "of_group_modify",
549 "of_group_delete",
550]
551
Rich Lanea06d0c32013-03-25 08:52:03 -0700552def sub_class_map(base_type, version):
553 """
554 Returns an iterable object giving the instance nameys and subclass types
555 for the base_type, version values
556 """
557 rv = []
558 if base_type not in inheritance_map:
559 return rv
560
561 for instance in inheritance_map[base_type]:
562 subcls = loxi_utils.instance_to_class(instance, base_type)
563 if not loxi_utils.class_in_version(subcls, version):
564 continue
565 rv.append((instance, subcls))
566
567 return rv
568
569################################################################
570#
571# Extension related data and functions
572#
573################################################################
574
575# Per OF Version, per experimenter, map exp msg type (subtype) to object IDs
576# @fixme Generate defines for OF_<exp>_SUBTYPE_<msg> for the values below?
577extension_message_subtype = {
578 # version 1.0
579 of_g.VERSION_1_0:dict( # Version 1.0 extensions
580 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700581 },
582 nicira = { # Nicira extensions, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700583 },
584 ),
585 of_g.VERSION_1_1:dict( # Version 1.0 extensions
586 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700587 },
588 ),
589 of_g.VERSION_1_2: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_3: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}
598
599# Set to empty dict if no extension actions defined
600# Per OF Version, per experimenter, map actions to subtype
601extension_action_subtype = {
602 # version 1.0
603 of_g.VERSION_1_0:dict( # Version 1.0 extensions
604 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700605 },
606 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700607 }
608 ),
609 of_g.VERSION_1_1:dict( # Version 1.0 extensions
610 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700611 },
612 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700613 }
614 ),
615 of_g.VERSION_1_2:dict( # Version 1.0 extensions
616 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700617 },
618 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700619 }
620 ),
621 of_g.VERSION_1_3:dict( # Version 1.0 extensions
622 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700623 },
624 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700625 }
626 ),
627}
628
629# Set to empty dict if no extension actions defined
630# Per OF Version, per experimenter, map actions to subtype
631extension_action_id_subtype = {
632 # version 1.0
633 of_g.VERSION_1_0:dict(),
634 of_g.VERSION_1_1:dict(),
635 of_g.VERSION_1_2:dict(),
636 of_g.VERSION_1_3:dict( # Version 1.3 extensions
637 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700638 },
639 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700640 }
641 ),
642}
643
644# Set to empty dict if no extension instructions defined
Rich Laneef7b9942013-11-18 16:29:28 -0800645extension_instruction_subtype = {
646 # version 1.0
647 of_g.VERSION_1_0:dict(),
648 of_g.VERSION_1_1:dict(),
649 of_g.VERSION_1_2:dict(),
650 of_g.VERSION_1_3:dict(
651 bsn = { # of_instruction_bsn_
652 },
653 nicira = { # of_instruction_nicira_
654 }
655 ),
656}
Rich Lanea06d0c32013-03-25 08:52:03 -0700657
658# Set to empty dict if no extension instructions defined
659extension_queue_prop_subtype = {}
660
661# Set to empty dict if no extension instructions defined
662extension_table_feature_prop_subtype = {}
663
664extension_objects = [
665 extension_message_subtype,
666 extension_action_subtype,
667 extension_action_id_subtype,
668 extension_instruction_subtype,
669 extension_queue_prop_subtype,
670 extension_table_feature_prop_subtype
671]
672
673################################################################
674# These are extension type generic (for messages, actions...)
675################################################################
676
677def extension_to_experimenter_name(cls):
678 """
679 Return the name of the experimenter if class is an
680 extension, else None
681
682 This is brute force; we search all extension data for a match
683 """
Andreas Wundsam53256162013-05-02 14:05:53 -0700684
Rich Lanea06d0c32013-03-25 08:52:03 -0700685 for ext_obj in extension_objects:
686 for version, exp_list in ext_obj.items():
687 for exp_name, classes in exp_list.items():
688 if cls in classes:
689 return exp_name
690 return None
691
692def extension_to_experimenter_id(cls):
693 """
694 Return the ID of the experimenter if class is an
695 extension, else None
696 """
697 exp_name = extension_to_experimenter_name(cls)
698 if exp_name:
699 return of_g.experimenter_name_to_id[exp_name]
700 return None
701
702def extension_to_experimenter_macro_name(cls):
703 """
704 Return the "macro name" of the ID of the experimenter if class is an
705 extension, else None
706 """
707 exp_name = extension_to_experimenter_name(cls)
708 if exp_name:
709 return "OF_EXPERIMENTER_ID_" + exp_name.upper()
710 return None
711
712def extension_to_subtype(cls, version):
713 """
714 Generic across all extension objects, return subtype identifier
715 """
716 for ext_obj in extension_objects:
717 for version, exp_list in ext_obj.items():
718 for exp_name, classes in exp_list.items():
719 if cls in classes:
720 return classes[cls]
721
722def class_is_extension(cls, version):
723 """
724 Return True if class, version is recognized as an extension
725 of any type (message, action....)
726
727 Accepts of_g.OF_VERSION_ANY
728 """
729
730 for ext_obj in extension_objects:
731 if cls_is_ext_obj(cls, version, ext_obj):
732 return True
733
734 return False
735
736# Internal
737def cls_is_ext_obj(cls, version, ext_obj):
738 """
739 @brief Return True if cls in an extension of type ext_obj
740 @param cls The class to check
741 @param version The version to check
742 @param ext_obj The extension object dictionary (messages, actions...)
743
744 Accepts of_g.VERSION_ANY
745 """
746
747 # Call with each version if "any" is passed
748 if version == of_g.VERSION_ANY:
749 for v in of_g.of_version_range:
750 if cls_is_ext_obj(cls, v, ext_obj):
751 return True
752 else: # Version specified
753 if version in ext_obj:
754 for exp, subtype_vals in ext_obj[version].items():
755 if cls in subtype_vals:
756 return True
757
758 return False
Andreas Wundsam53256162013-05-02 14:05:53 -0700759
Rich Lanea06d0c32013-03-25 08:52:03 -0700760################################################################
761# These are extension message specific
762################################################################
763
764def message_is_extension(cls, version):
765 """
766 Return True if cls, version is recognized as an extension
767 This is brute force, searching records for a match
768 """
769 return cls_is_ext_obj(cls, version, extension_message_subtype)
770
771def extension_message_to_subtype(cls, version):
772 """
773 Return the subtype of the experimenter message if the class is an
774 extension, else None
775 """
776 if version in extension_message_subtype:
777 for exp, classes in extension_message_subtype[version].items():
778 for ext_class, subtype in classes.items():
779 if cls == ext_class:
780 return subtype
781 return None
782
783################################################################
784# These are extension action specific
785################################################################
786
787def action_is_extension(cls, version):
788 """
789 Return True if cls, version is recognized as an action extension
790 This is brute force, searching records for a match
791 """
792 return cls_is_ext_obj(cls, version, extension_action_subtype)
793
794def extension_action_to_subtype(cls, version):
795 """
796 Return the ID of the action subtype (for its experimenteer)
797 if class is an action extension, else None
798 """
799 if version in extension_action_subtype:
800 for exp, classes in extension_action_subtype[version].items():
801 if cls in classes:
802 return classes[cls]
803
804 return None
805
806################################################################
807# These are extension action specific
808################################################################
809
810def action_id_is_extension(cls, version):
811 """
812 Return True if cls, version is recognized as an action ID extension
813 This is brute force, searching records for a match
814 """
815 if version not in [of_g.VERSION_1_3]: # Action IDs only 1.3
816 return False
817 return cls_is_ext_obj(cls, version, extension_action_id_subtype)
818
819def extension_action_id_to_subtype(cls, version):
820 """
821 Return the ID of the action ID subtype (for its experimenteer)
822 if class is an action ID extension, else None
823 """
824 if version in extension_action_id_subtype:
825 for exp, classes in extension_action_id_subtype[version].items():
826 if cls in classes:
827 return classes[cls]
828
829 return None
830
831################################################################
832# These are extension instruction specific
833################################################################
834
835def instruction_is_extension(cls, version):
836 """
837 Return True if cls, version is recognized as an instruction extension
838 This is brute force, searching records for a match
839 """
840 return cls_is_ext_obj(cls, version, extension_instruction_subtype)
841
842################################################################
843# These are extension queue_prop specific
844################################################################
845
846def queue_prop_is_extension(cls, version):
847 """
848 Return True if cls, version is recognized as an instruction extension
849 This is brute force, searching records for a match
850 """
851 return cls_is_ext_obj(cls, version, extension_queue_prop_subtype)
852
853################################################################
854# These are extension table_feature_prop specific
855################################################################
856
857def table_feature_prop_is_extension(cls, version):
858 """
859 Return True if cls, version is recognized as an instruction extension
860 This is brute force, searching records for a match
861 """
862 return cls_is_ext_obj(cls, version,
863 extension_table_feature_prop_subtype)