blob: 2a535194d3aa29eb8a3cf210c1bbc00ef9dc1351 [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
Rich Lane713d9282013-12-30 15:21:35 -0800139bsn_tlv_types = {
140 of_g.VERSION_1_0:dict(),
141 of_g.VERSION_1_1:dict(),
142 of_g.VERSION_1_2:dict(),
143 of_g.VERSION_1_3:dict(),
144 }
145
Rich Lanea06d0c32013-03-25 08:52:03 -0700146# All inheritance data for non-messages
147inheritance_data = dict(
148 of_instruction = instruction_types,
Rich Lane4def6972013-12-09 17:44:43 -0800149 of_instruction_id = instruction_id_types,
Rich Lanea06d0c32013-03-25 08:52:03 -0700150 of_action = action_types,
151 of_action_id = action_id_types,
152 of_oxm = oxm_types,
153 of_queue_prop = queue_prop_types,
154 of_hello_elem = hello_elem_types,
155 of_table_feature_prop = table_feature_prop_types,
Dan Talaycoc0e802e2013-05-18 23:52:39 -0700156 of_meter_band = meter_band_types,
157 # BSN specific inheritance extensions
Rich Lane713d9282013-12-30 15:21:35 -0800158 of_bsn_vport = bsn_vport_types,
159 of_bsn_tlv = bsn_tlv_types,
Rich Lanea06d0c32013-03-25 08:52:03 -0700160 )
161
Rich Lanea06d0c32013-03-25 08:52:03 -0700162def class_is_virtual(cls):
163 """
164 Returns True if cls is a virtual class
165 """
Rich Lanea06d0c32013-03-25 08:52:03 -0700166 if cls.find("header") > 0:
167 return True
168 if loxi_utils.class_is_list(cls):
169 return True
Rich Lane043a3d82013-12-10 10:57:30 -0800170 return loxi_globals.unified.class_by_name(cls).virtual
Rich Lanea06d0c32013-03-25 08:52:03 -0700171
172################################################################
173#
174# These are message types
175#
176################################################################
177
Rich Lanedf847e32013-05-29 16:57:30 -0700178# The hardcoded message types are for inheritance parents
Rich Lanea06d0c32013-03-25 08:52:03 -0700179message_types = {
180 # version 1.0
181 of_g.VERSION_1_0: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 = 16,
186 stats_reply = 17,
Rich Lanea06d0c32013-03-25 08:52:03 -0700187 ),
188
189 # version 1.1
190 of_g.VERSION_1_1: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 Lanee3113672013-12-06 17:09:57 -0800194 group_mod = 15,
Rich Lanea06d0c32013-03-25 08:52:03 -0700195 stats_request = 18,
196 stats_reply = 19,
Rich Lanea06d0c32013-03-25 08:52:03 -0700197 ),
198
199 # version 1.2
200 of_g.VERSION_1_2:dict(
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700201 error_msg = 1,
Rich Lanedf847e32013-05-29 16:57:30 -0700202 experimenter = 4,
Rich Lanea06d0c32013-03-25 08:52:03 -0700203 flow_mod = 14,
Rich Lanee3113672013-12-06 17:09:57 -0800204 group_mod = 15,
Rich Lanea06d0c32013-03-25 08:52:03 -0700205 stats_request = 18,
206 stats_reply = 19,
Rich Lanea06d0c32013-03-25 08:52:03 -0700207 ),
208
209 # version 1.3
210 of_g.VERSION_1_3:dict(
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700211 error_msg = 1,
Rich Lanedf847e32013-05-29 16:57:30 -0700212 experimenter = 4,
Rich Lanea06d0c32013-03-25 08:52:03 -0700213 flow_mod = 14,
Rich Lanee3113672013-12-06 17:09:57 -0800214 group_mod = 15,
Rich Lanea06d0c32013-03-25 08:52:03 -0700215 stats_request = 18, # FIXME Multipart
216 stats_reply = 19,
Rich Lanea06d0c32013-03-25 08:52:03 -0700217 )
218 }
219
220################################################################
221#
222# These are other objects that have a notion of type but are
223# not (yet) promoted to objects with inheritance
224#
225################################################################
226
227stats_types = {
228 # version 1.0
229 of_g.VERSION_1_0:dict(
230 desc = 0,
231 flow = 1,
232 aggregate = 2,
233 table = 3,
234 port = 4,
235 queue = 5,
236 experimenter = 0xffff
237 ),
238
239 # version 1.1
240 of_g.VERSION_1_1:dict(
241 desc = 0,
242 flow = 1,
243 aggregate = 2,
244 table = 3,
245 port = 4,
246 queue = 5,
247 group = 6,
248 group_desc = 7,
249 experimenter = 0xffff
250 ),
251
252 # version 1.2
253 of_g.VERSION_1_2:dict(
254 desc = 0,
255 flow = 1,
256 aggregate = 2,
257 table = 3,
258 port = 4,
259 queue = 5,
260 group = 6,
261 group_desc = 7,
262 group_features = 8,
263 experimenter = 0xffff
264 ),
265
266 # version 1.3
267 of_g.VERSION_1_3:dict(
268 desc = 0,
269 flow = 1,
270 aggregate = 2,
271 table = 3,
272 port = 4,
273 queue = 5,
274 group = 6,
275 group_desc = 7,
276 group_features = 8,
277 meter = 9,
278 meter_config = 10,
279 meter_features = 11,
280 table_features = 12,
281 port_desc = 13,
Rich Lane353a79f2013-11-13 10:39:56 -0800282 experimenter = 0xffff,
Wilson Ng45386fb2013-12-03 13:46:42 -0800283 bsn_lacp = 0xffff,
xinwu358e6162013-12-04 16:49:48 -0800284 bsn_switch_pipeline = 0xffff,
285 bsn_port_counter = 0xffff,
286 bsn_vlan_counter = 0xffff
Rich Lanea06d0c32013-03-25 08:52:03 -0700287 )
288 }
289
290common_flow_mod_types = dict(
291 add = 0,
292 modify = 1,
293 modify_strict = 2,
294 delete = 3,
295 delete_strict = 4
296 )
297
298flow_mod_types = {
299 # version 1.0
300 of_g.VERSION_1_0:common_flow_mod_types,
301 of_g.VERSION_1_1:common_flow_mod_types,
302 of_g.VERSION_1_2:common_flow_mod_types,
303 of_g.VERSION_1_3:common_flow_mod_types
304 }
305
306# These do not translate to objects (yet)
307error_types = {
308 # version 1.0
309 of_g.VERSION_1_0:dict(
310 hello_failed = 0,
311 bad_request = 1,
312 bad_action = 2,
313 flow_mod_failed = 3,
314 port_mod_failed = 4,
315 queue_op_failed = 5
316 ),
317
318 # version 1.1
319 of_g.VERSION_1_1: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 ),
332
333 # version 1.2
334 of_g.VERSION_1_2:dict(
335 hello_failed = 0,
336 bad_request = 1,
337 bad_action = 2,
338 bad_instruction = 3,
339 bad_match = 4,
340 flow_mod_failed = 5,
341 group_mod_failed = 6,
342 port_mod_failed = 7,
343 table_mod_failed = 8,
344 queue_op_failed = 9,
345 switch_config_failed = 10,
346 role_request_failed = 11,
347 experimenter = 0xffff
348 ),
349
350 # version 1.3
351 of_g.VERSION_1_3:dict(
352 hello_failed = 0,
353 bad_request = 1,
354 bad_action = 2,
355 bad_instruction = 3,
356 bad_match = 4,
357 flow_mod_failed = 5,
358 group_mod_failed = 6,
359 port_mod_failed = 7,
360 table_mod_failed = 8,
361 queue_op_failed = 9,
362 switch_config_failed = 10,
363 role_request_failed = 11,
364 meter_mod_failed = 12,
365 table_features_failed= 13,
366 experimenter = 0xffff
367 )
368 }
369
Rich Lanee3113672013-12-06 17:09:57 -0800370group_mod_types = {
371 # version 1.0
372 of_g.VERSION_1_0:dict(),
373
374 # version 1.1
375 of_g.VERSION_1_1:dict(
376 add = 0,
377 modify = 1,
378 delete = 2
379 ),
380
381 # version 1.2
382 of_g.VERSION_1_2:dict(
383 add = 0,
384 modify = 1,
385 delete = 2
386 ),
387
388 # version 1.3
389 of_g.VERSION_1_3:dict(
390 add = 0,
391 modify = 1,
392 delete = 2
393 )
394 }
395
Rich Lanea06d0c32013-03-25 08:52:03 -0700396##
397# These are the objects whose length is specified by an external
398# reference, specifically another data member in the class.
Andreas Wundsam53256162013-05-02 14:05:53 -0700399#
Rich Lanea06d0c32013-03-25 08:52:03 -0700400#external_length_spec = {
401# ("of_packet_out", "actions", OF_VERSION_1_0) : "actions_len",
402# ("of_packet_out", "actions", OF_VERSION_1_1) : "actions_len",
403# ("of_packet_out", "actions", OF_VERSION_1_2) : "actions_len",
404# ("of_packet_out", "actions", OF_VERSION_1_3) : "actions_len"
405#}
406
407
408################################################################
409#
Andreas Wundsam53256162013-05-02 14:05:53 -0700410# type_val is the primary data structure that maps an
Rich Lanea06d0c32013-03-25 08:52:03 -0700411# (class_name, version) pair to the wire data type value
412#
413################################################################
414
415type_val = dict()
Rich Lane6bb28dd2013-05-13 15:19:14 -0700416inheritance_map = dict()
Rich Lanea06d0c32013-03-25 08:52:03 -0700417
Rich Lane6bb28dd2013-05-13 15:19:14 -0700418def generate_maps():
419 for parent, versioned in inheritance_data.items():
420 inheritance_map[parent] = set()
421 for ver, subclasses in versioned.items():
422 for subcls in subclasses:
423 inheritance_map[parent].add(subcls)
Rich Lanea06d0c32013-03-25 08:52:03 -0700424
Rich Lane6bb28dd2013-05-13 15:19:14 -0700425 for version, classes in message_types.items():
426 for cls in classes:
427 name = "of_" + cls
428 type_val[(name, version)] = classes[cls]
Rich Lanea06d0c32013-03-25 08:52:03 -0700429
Rich Lane6bb28dd2013-05-13 15:19:14 -0700430 for parent, versioned in inheritance_data.items():
431 for version, subclasses in versioned.items():
432 for subcls, value in subclasses.items():
433 name = parent + "_" + subcls
434 type_val[(name, version)] = value
435
436 # Special case OF-1.2 match type
Rich Lanea72c98e2013-07-12 16:40:06 -0700437 type_val[("of_match_v3", of_g.VERSION_1_2)] = 1
438 type_val[("of_match_v3", of_g.VERSION_1_3)] = 1
Rich Lanea06d0c32013-03-25 08:52:03 -0700439
440# Utility function
441def dict_to_array(d, m_val, def_val=-1):
442 """
443 Given a dictionary, d, with each value a small integer,
444 produce an array indexed by the integer whose value is the key.
445 @param d The dictionary
446 @param m_val Ignore values greater than m_val
447 @param def_val The default value (for indices not in range of d)
448 """
449
450 # Get the max value in range for hash
451 max_val = 0
452 for key in d:
453 if (d[key] > max_val) and (d[key] < m_val):
454 max_val = d[key]
455 ar = []
456 for x in range(0, max_val + 1):
457 ar.append(def_val)
458 for key in d:
459 if (d[key] < m_val):
460 ar[d[key]] = key
461 return ar
462
463def type_array_len(version_indexed, max_val):
464 """
465 Given versioned information about a type, calculate how long
466 the unified array should be.
467
Andreas Wundsam53256162013-05-02 14:05:53 -0700468 @param version_indexed A dict indexed by version. Each value is a
Rich Lanea06d0c32013-03-25 08:52:03 -0700469 dict indexed by a name and whose value is an integer
470 @param max_val Ignore values greater than this for length calcs
471 """
472 # First, find the max length of all arrays
473 arr_len = 0
474 for version, val_dict in version_indexed.items():
475 ar = dict_to_array(val_dict, max_val, invalid_type)
476 if arr_len < len(ar):
477 arr_len = len(ar)
478 return arr_len
479
480# FIXME: Need to move update for multipart messages
481
482stats_reply_list = [
483 "of_aggregate_stats_reply",
484 "of_desc_stats_reply",
485 "of_experimenter_stats_reply",
486 "of_flow_stats_reply",
487 "of_group_stats_reply",
488 "of_group_desc_stats_reply",
489 "of_group_features_stats_reply",
490 "of_meter_stats_reply",
491 "of_meter_config_stats_reply",
492 "of_meter_features_stats_reply",
493 "of_port_stats_reply",
494 "of_port_desc_stats_reply",
495 "of_queue_stats_reply",
496 "of_table_stats_reply",
Rich Lane353a79f2013-11-13 10:39:56 -0800497 "of_table_features_stats_reply",
498 "of_bsn_stats_reply",
499 "of_bsn_lacp_stats_reply",
Wilson Ng27e4beb2013-12-03 12:33:01 -0800500 "of_bsn_switch_pipeline_stats_reply",
xinwu358e6162013-12-04 16:49:48 -0800501 "of_bsn_port_counter_stats_reply",
502 "of_bsn_vlan_counter_stats_reply",
Rich Lanea06d0c32013-03-25 08:52:03 -0700503]
504
505stats_request_list = [
506 "of_aggregate_stats_request",
507 "of_desc_stats_request",
508 "of_experimenter_stats_request",
509 "of_flow_stats_request",
510 "of_group_stats_request",
511 "of_group_desc_stats_request",
512 "of_group_features_stats_request",
513 "of_meter_stats_request",
514 "of_meter_config_stats_request",
515 "of_meter_features_stats_request",
516 "of_port_stats_request",
517 "of_port_desc_stats_request",
518 "of_queue_stats_request",
519 "of_table_stats_request",
Rich Lane353a79f2013-11-13 10:39:56 -0800520 "of_table_features_stats_request",
521 "of_bsn_stats_request",
522 "of_bsn_lacp_stats_request",
Wilson Ng27e4beb2013-12-03 12:33:01 -0800523 "of_bsn_switch_pipeline_stats_request",
xinwu358e6162013-12-04 16:49:48 -0800524 "of_bsn_port_counter_stats_request",
525 "of_bsn_vlan_counter_stats_request",
Rich Lanea06d0c32013-03-25 08:52:03 -0700526]
527
528flow_mod_list = [
529 "of_flow_add",
530 "of_flow_modify",
531 "of_flow_modify_strict",
532 "of_flow_delete",
533 "of_flow_delete_strict"
534]
535
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700536error_msg_list = [
537 "of_hello_failed_error_msg",
538 "of_bad_request_error_msg",
539 "of_bad_action_error_msg",
540 "of_bad_instruction_error_msg",
541 "of_bad_match_error_msg",
542 "of_flow_mod_failed_error_msg",
543 "of_group_mod_failed_error_msg",
544 "of_port_mod_failed_error_msg",
545 "of_table_mod_failed_error_msg",
546 "of_queue_op_failed_error_msg",
547 "of_switch_config_failed_error_msg",
548 "of_role_request_failed_error_msg",
549 "of_meter_mod_failed_error_msg",
550 "of_table_features_failed_error_msg",
551 "of_experimenter_error_msg"
552]
553
Rich Lanee3113672013-12-06 17:09:57 -0800554group_mod_list = [
555 "of_group_add",
556 "of_group_modify",
557 "of_group_delete",
558]
559
Rich Lanea06d0c32013-03-25 08:52:03 -0700560def sub_class_map(base_type, version):
561 """
562 Returns an iterable object giving the instance nameys and subclass types
563 for the base_type, version values
564 """
565 rv = []
566 if base_type not in inheritance_map:
567 return rv
568
569 for instance in inheritance_map[base_type]:
570 subcls = loxi_utils.instance_to_class(instance, base_type)
571 if not loxi_utils.class_in_version(subcls, version):
572 continue
573 rv.append((instance, subcls))
574
575 return rv
576
577################################################################
578#
579# Extension related data and functions
580#
581################################################################
582
583# Per OF Version, per experimenter, map exp msg type (subtype) to object IDs
584# @fixme Generate defines for OF_<exp>_SUBTYPE_<msg> for the values below?
585extension_message_subtype = {
586 # version 1.0
587 of_g.VERSION_1_0:dict( # Version 1.0 extensions
588 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700589 },
590 nicira = { # Nicira extensions, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700591 },
592 ),
593 of_g.VERSION_1_1: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_2: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 of_g.VERSION_1_3:dict( # Version 1.0 extensions
602 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700603 },
604 ),
605}
606
607# Set to empty dict if no extension actions defined
608# Per OF Version, per experimenter, map actions to subtype
609extension_action_subtype = {
610 # version 1.0
611 of_g.VERSION_1_0:dict( # Version 1.0 extensions
612 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700613 },
614 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700615 }
616 ),
617 of_g.VERSION_1_1:dict( # Version 1.0 extensions
618 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700619 },
620 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700621 }
622 ),
623 of_g.VERSION_1_2:dict( # Version 1.0 extensions
624 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700625 },
626 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700627 }
628 ),
629 of_g.VERSION_1_3:dict( # Version 1.0 extensions
630 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700631 },
632 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700633 }
634 ),
635}
636
637# Set to empty dict if no extension actions defined
638# Per OF Version, per experimenter, map actions to subtype
639extension_action_id_subtype = {
640 # version 1.0
641 of_g.VERSION_1_0:dict(),
642 of_g.VERSION_1_1:dict(),
643 of_g.VERSION_1_2:dict(),
644 of_g.VERSION_1_3:dict( # Version 1.3 extensions
645 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700646 },
647 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700648 }
649 ),
650}
651
652# Set to empty dict if no extension instructions defined
Rich Laneef7b9942013-11-18 16:29:28 -0800653extension_instruction_subtype = {
654 # version 1.0
655 of_g.VERSION_1_0:dict(),
656 of_g.VERSION_1_1:dict(),
657 of_g.VERSION_1_2:dict(),
658 of_g.VERSION_1_3:dict(
659 bsn = { # of_instruction_bsn_
660 },
661 nicira = { # of_instruction_nicira_
662 }
663 ),
664}
Rich Lanea06d0c32013-03-25 08:52:03 -0700665
666# Set to empty dict if no extension instructions defined
667extension_queue_prop_subtype = {}
668
669# Set to empty dict if no extension instructions defined
670extension_table_feature_prop_subtype = {}
671
672extension_objects = [
673 extension_message_subtype,
674 extension_action_subtype,
675 extension_action_id_subtype,
676 extension_instruction_subtype,
677 extension_queue_prop_subtype,
678 extension_table_feature_prop_subtype
679]
680
681################################################################
682# These are extension type generic (for messages, actions...)
683################################################################
684
685def extension_to_experimenter_name(cls):
686 """
687 Return the name of the experimenter if class is an
688 extension, else None
689
690 This is brute force; we search all extension data for a match
691 """
Andreas Wundsam53256162013-05-02 14:05:53 -0700692
Rich Lanea06d0c32013-03-25 08:52:03 -0700693 for ext_obj in extension_objects:
694 for version, exp_list in ext_obj.items():
695 for exp_name, classes in exp_list.items():
696 if cls in classes:
697 return exp_name
698 return None
699
700def extension_to_experimenter_id(cls):
701 """
702 Return the ID of the experimenter if class is an
703 extension, else None
704 """
705 exp_name = extension_to_experimenter_name(cls)
706 if exp_name:
707 return of_g.experimenter_name_to_id[exp_name]
708 return None
709
710def extension_to_experimenter_macro_name(cls):
711 """
712 Return the "macro name" of the ID of the experimenter if class is an
713 extension, else None
714 """
715 exp_name = extension_to_experimenter_name(cls)
716 if exp_name:
717 return "OF_EXPERIMENTER_ID_" + exp_name.upper()
718 return None
719
720def extension_to_subtype(cls, version):
721 """
722 Generic across all extension objects, return subtype identifier
723 """
724 for ext_obj in extension_objects:
725 for version, exp_list in ext_obj.items():
726 for exp_name, classes in exp_list.items():
727 if cls in classes:
728 return classes[cls]
729
730def class_is_extension(cls, version):
731 """
732 Return True if class, version is recognized as an extension
733 of any type (message, action....)
734
735 Accepts of_g.OF_VERSION_ANY
736 """
737
738 for ext_obj in extension_objects:
739 if cls_is_ext_obj(cls, version, ext_obj):
740 return True
741
742 return False
743
744# Internal
745def cls_is_ext_obj(cls, version, ext_obj):
746 """
747 @brief Return True if cls in an extension of type ext_obj
748 @param cls The class to check
749 @param version The version to check
750 @param ext_obj The extension object dictionary (messages, actions...)
751
752 Accepts of_g.VERSION_ANY
753 """
754
755 # Call with each version if "any" is passed
756 if version == of_g.VERSION_ANY:
757 for v in of_g.of_version_range:
758 if cls_is_ext_obj(cls, v, ext_obj):
759 return True
760 else: # Version specified
761 if version in ext_obj:
762 for exp, subtype_vals in ext_obj[version].items():
763 if cls in subtype_vals:
764 return True
765
766 return False
Andreas Wundsam53256162013-05-02 14:05:53 -0700767
Rich Lanea06d0c32013-03-25 08:52:03 -0700768################################################################
769# These are extension message specific
770################################################################
771
772def message_is_extension(cls, version):
773 """
774 Return True if cls, version is recognized as an extension
775 This is brute force, searching records for a match
776 """
777 return cls_is_ext_obj(cls, version, extension_message_subtype)
778
779def extension_message_to_subtype(cls, version):
780 """
781 Return the subtype of the experimenter message if the class is an
782 extension, else None
783 """
784 if version in extension_message_subtype:
785 for exp, classes in extension_message_subtype[version].items():
786 for ext_class, subtype in classes.items():
787 if cls == ext_class:
788 return subtype
789 return None
790
791################################################################
792# These are extension action specific
793################################################################
794
795def action_is_extension(cls, version):
796 """
797 Return True if cls, version is recognized as an action extension
798 This is brute force, searching records for a match
799 """
800 return cls_is_ext_obj(cls, version, extension_action_subtype)
801
802def extension_action_to_subtype(cls, version):
803 """
804 Return the ID of the action subtype (for its experimenteer)
805 if class is an action extension, else None
806 """
807 if version in extension_action_subtype:
808 for exp, classes in extension_action_subtype[version].items():
809 if cls in classes:
810 return classes[cls]
811
812 return None
813
814################################################################
815# These are extension action specific
816################################################################
817
818def action_id_is_extension(cls, version):
819 """
820 Return True if cls, version is recognized as an action ID extension
821 This is brute force, searching records for a match
822 """
823 if version not in [of_g.VERSION_1_3]: # Action IDs only 1.3
824 return False
825 return cls_is_ext_obj(cls, version, extension_action_id_subtype)
826
827def extension_action_id_to_subtype(cls, version):
828 """
829 Return the ID of the action ID subtype (for its experimenteer)
830 if class is an action ID extension, else None
831 """
832 if version in extension_action_id_subtype:
833 for exp, classes in extension_action_id_subtype[version].items():
834 if cls in classes:
835 return classes[cls]
836
837 return None
838
839################################################################
840# These are extension instruction specific
841################################################################
842
843def instruction_is_extension(cls, version):
844 """
845 Return True if cls, version is recognized as an instruction extension
846 This is brute force, searching records for a match
847 """
848 return cls_is_ext_obj(cls, version, extension_instruction_subtype)
849
850################################################################
851# These are extension queue_prop specific
852################################################################
853
854def queue_prop_is_extension(cls, version):
855 """
856 Return True if cls, version is recognized as an instruction extension
857 This is brute force, searching records for a match
858 """
859 return cls_is_ext_obj(cls, version, extension_queue_prop_subtype)
860
861################################################################
862# These are extension table_feature_prop specific
863################################################################
864
865def table_feature_prop_is_extension(cls, version):
866 """
867 Return True if cls, version is recognized as an instruction extension
868 This is brute force, searching records for a match
869 """
870 return cls_is_ext_obj(cls, version,
871 extension_table_feature_prop_subtype)