blob: ae5f481c5bb7e64b5d645fb29d9fcd2df01ae2e7 [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 Lanee3113672013-12-06 17:09:57 -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", "of_group_mod"]:
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 Lanee3113672013-12-06 17:09:57 -0800185 group_mod = 15,
Rich Lanea06d0c32013-03-25 08:52:03 -0700186 stats_request = 18,
187 stats_reply = 19,
Rich Lanea06d0c32013-03-25 08:52:03 -0700188 ),
189
190 # version 1.2
191 of_g.VERSION_1_2:dict(
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700192 error_msg = 1,
Rich Lanedf847e32013-05-29 16:57:30 -0700193 experimenter = 4,
Rich Lanea06d0c32013-03-25 08:52:03 -0700194 flow_mod = 14,
Rich Lanee3113672013-12-06 17:09:57 -0800195 group_mod = 15,
Rich Lanea06d0c32013-03-25 08:52:03 -0700196 stats_request = 18,
197 stats_reply = 19,
Rich Lanea06d0c32013-03-25 08:52:03 -0700198 ),
199
200 # version 1.3
201 of_g.VERSION_1_3:dict(
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700202 error_msg = 1,
Rich Lanedf847e32013-05-29 16:57:30 -0700203 experimenter = 4,
Rich Lanea06d0c32013-03-25 08:52:03 -0700204 flow_mod = 14,
Rich Lanee3113672013-12-06 17:09:57 -0800205 group_mod = 15,
Rich Lanea06d0c32013-03-25 08:52:03 -0700206 stats_request = 18, # FIXME Multipart
207 stats_reply = 19,
Rich Lanea06d0c32013-03-25 08:52:03 -0700208 )
209 }
210
211################################################################
212#
213# These are other objects that have a notion of type but are
214# not (yet) promoted to objects with inheritance
215#
216################################################################
217
218stats_types = {
219 # version 1.0
220 of_g.VERSION_1_0:dict(
221 desc = 0,
222 flow = 1,
223 aggregate = 2,
224 table = 3,
225 port = 4,
226 queue = 5,
227 experimenter = 0xffff
228 ),
229
230 # version 1.1
231 of_g.VERSION_1_1:dict(
232 desc = 0,
233 flow = 1,
234 aggregate = 2,
235 table = 3,
236 port = 4,
237 queue = 5,
238 group = 6,
239 group_desc = 7,
240 experimenter = 0xffff
241 ),
242
243 # version 1.2
244 of_g.VERSION_1_2:dict(
245 desc = 0,
246 flow = 1,
247 aggregate = 2,
248 table = 3,
249 port = 4,
250 queue = 5,
251 group = 6,
252 group_desc = 7,
253 group_features = 8,
254 experimenter = 0xffff
255 ),
256
257 # version 1.3
258 of_g.VERSION_1_3:dict(
259 desc = 0,
260 flow = 1,
261 aggregate = 2,
262 table = 3,
263 port = 4,
264 queue = 5,
265 group = 6,
266 group_desc = 7,
267 group_features = 8,
268 meter = 9,
269 meter_config = 10,
270 meter_features = 11,
271 table_features = 12,
272 port_desc = 13,
Rich Lane353a79f2013-11-13 10:39:56 -0800273 experimenter = 0xffff,
Wilson Ng45386fb2013-12-03 13:46:42 -0800274 bsn_lacp = 0xffff,
xinwu358e6162013-12-04 16:49:48 -0800275 bsn_switch_pipeline = 0xffff,
276 bsn_port_counter = 0xffff,
277 bsn_vlan_counter = 0xffff
Rich Lanea06d0c32013-03-25 08:52:03 -0700278 )
279 }
280
281common_flow_mod_types = dict(
282 add = 0,
283 modify = 1,
284 modify_strict = 2,
285 delete = 3,
286 delete_strict = 4
287 )
288
289flow_mod_types = {
290 # version 1.0
291 of_g.VERSION_1_0:common_flow_mod_types,
292 of_g.VERSION_1_1:common_flow_mod_types,
293 of_g.VERSION_1_2:common_flow_mod_types,
294 of_g.VERSION_1_3:common_flow_mod_types
295 }
296
297# These do not translate to objects (yet)
298error_types = {
299 # version 1.0
300 of_g.VERSION_1_0:dict(
301 hello_failed = 0,
302 bad_request = 1,
303 bad_action = 2,
304 flow_mod_failed = 3,
305 port_mod_failed = 4,
306 queue_op_failed = 5
307 ),
308
309 # version 1.1
310 of_g.VERSION_1_1:dict(
311 hello_failed = 0,
312 bad_request = 1,
313 bad_action = 2,
314 bad_instruction = 3,
315 bad_match = 4,
316 flow_mod_failed = 5,
317 group_mod_failed = 6,
318 port_mod_failed = 7,
319 table_mod_failed = 8,
320 queue_op_failed = 9,
321 switch_config_failed = 10
322 ),
323
324 # version 1.2
325 of_g.VERSION_1_2:dict(
326 hello_failed = 0,
327 bad_request = 1,
328 bad_action = 2,
329 bad_instruction = 3,
330 bad_match = 4,
331 flow_mod_failed = 5,
332 group_mod_failed = 6,
333 port_mod_failed = 7,
334 table_mod_failed = 8,
335 queue_op_failed = 9,
336 switch_config_failed = 10,
337 role_request_failed = 11,
338 experimenter = 0xffff
339 ),
340
341 # version 1.3
342 of_g.VERSION_1_3:dict(
343 hello_failed = 0,
344 bad_request = 1,
345 bad_action = 2,
346 bad_instruction = 3,
347 bad_match = 4,
348 flow_mod_failed = 5,
349 group_mod_failed = 6,
350 port_mod_failed = 7,
351 table_mod_failed = 8,
352 queue_op_failed = 9,
353 switch_config_failed = 10,
354 role_request_failed = 11,
355 meter_mod_failed = 12,
356 table_features_failed= 13,
357 experimenter = 0xffff
358 )
359 }
360
Rich Lanee3113672013-12-06 17:09:57 -0800361group_mod_types = {
362 # version 1.0
363 of_g.VERSION_1_0:dict(),
364
365 # version 1.1
366 of_g.VERSION_1_1:dict(
367 add = 0,
368 modify = 1,
369 delete = 2
370 ),
371
372 # version 1.2
373 of_g.VERSION_1_2:dict(
374 add = 0,
375 modify = 1,
376 delete = 2
377 ),
378
379 # version 1.3
380 of_g.VERSION_1_3:dict(
381 add = 0,
382 modify = 1,
383 delete = 2
384 )
385 }
386
Rich Lanea06d0c32013-03-25 08:52:03 -0700387##
388# These are the objects whose length is specified by an external
389# reference, specifically another data member in the class.
Andreas Wundsam53256162013-05-02 14:05:53 -0700390#
Rich Lanea06d0c32013-03-25 08:52:03 -0700391#external_length_spec = {
392# ("of_packet_out", "actions", OF_VERSION_1_0) : "actions_len",
393# ("of_packet_out", "actions", OF_VERSION_1_1) : "actions_len",
394# ("of_packet_out", "actions", OF_VERSION_1_2) : "actions_len",
395# ("of_packet_out", "actions", OF_VERSION_1_3) : "actions_len"
396#}
397
398
399################################################################
400#
Andreas Wundsam53256162013-05-02 14:05:53 -0700401# type_val is the primary data structure that maps an
Rich Lanea06d0c32013-03-25 08:52:03 -0700402# (class_name, version) pair to the wire data type value
403#
404################################################################
405
406type_val = dict()
Rich Lane6bb28dd2013-05-13 15:19:14 -0700407inheritance_map = dict()
Rich Lanea06d0c32013-03-25 08:52:03 -0700408
Rich Lane6bb28dd2013-05-13 15:19:14 -0700409def generate_maps():
410 for parent, versioned in inheritance_data.items():
411 inheritance_map[parent] = set()
412 for ver, subclasses in versioned.items():
413 for subcls in subclasses:
414 inheritance_map[parent].add(subcls)
Rich Lanea06d0c32013-03-25 08:52:03 -0700415
Rich Lane6bb28dd2013-05-13 15:19:14 -0700416 for version, classes in message_types.items():
417 for cls in classes:
418 name = "of_" + cls
419 type_val[(name, version)] = classes[cls]
Rich Lanea06d0c32013-03-25 08:52:03 -0700420
Rich Lane6bb28dd2013-05-13 15:19:14 -0700421 for parent, versioned in inheritance_data.items():
422 for version, subclasses in versioned.items():
423 for subcls, value in subclasses.items():
424 name = parent + "_" + subcls
425 type_val[(name, version)] = value
426
427 # Special case OF-1.2 match type
Rich Lanea72c98e2013-07-12 16:40:06 -0700428 type_val[("of_match_v3", of_g.VERSION_1_2)] = 1
429 type_val[("of_match_v3", of_g.VERSION_1_3)] = 1
Rich Lanea06d0c32013-03-25 08:52:03 -0700430
431# Utility function
432def dict_to_array(d, m_val, def_val=-1):
433 """
434 Given a dictionary, d, with each value a small integer,
435 produce an array indexed by the integer whose value is the key.
436 @param d The dictionary
437 @param m_val Ignore values greater than m_val
438 @param def_val The default value (for indices not in range of d)
439 """
440
441 # Get the max value in range for hash
442 max_val = 0
443 for key in d:
444 if (d[key] > max_val) and (d[key] < m_val):
445 max_val = d[key]
446 ar = []
447 for x in range(0, max_val + 1):
448 ar.append(def_val)
449 for key in d:
450 if (d[key] < m_val):
451 ar[d[key]] = key
452 return ar
453
454def type_array_len(version_indexed, max_val):
455 """
456 Given versioned information about a type, calculate how long
457 the unified array should be.
458
Andreas Wundsam53256162013-05-02 14:05:53 -0700459 @param version_indexed A dict indexed by version. Each value is a
Rich Lanea06d0c32013-03-25 08:52:03 -0700460 dict indexed by a name and whose value is an integer
461 @param max_val Ignore values greater than this for length calcs
462 """
463 # First, find the max length of all arrays
464 arr_len = 0
465 for version, val_dict in version_indexed.items():
466 ar = dict_to_array(val_dict, max_val, invalid_type)
467 if arr_len < len(ar):
468 arr_len = len(ar)
469 return arr_len
470
471# FIXME: Need to move update for multipart messages
472
473stats_reply_list = [
474 "of_aggregate_stats_reply",
475 "of_desc_stats_reply",
476 "of_experimenter_stats_reply",
477 "of_flow_stats_reply",
478 "of_group_stats_reply",
479 "of_group_desc_stats_reply",
480 "of_group_features_stats_reply",
481 "of_meter_stats_reply",
482 "of_meter_config_stats_reply",
483 "of_meter_features_stats_reply",
484 "of_port_stats_reply",
485 "of_port_desc_stats_reply",
486 "of_queue_stats_reply",
487 "of_table_stats_reply",
Rich Lane353a79f2013-11-13 10:39:56 -0800488 "of_table_features_stats_reply",
489 "of_bsn_stats_reply",
490 "of_bsn_lacp_stats_reply",
Wilson Ng27e4beb2013-12-03 12:33:01 -0800491 "of_bsn_switch_pipeline_stats_reply",
xinwu358e6162013-12-04 16:49:48 -0800492 "of_bsn_port_counter_stats_reply",
493 "of_bsn_vlan_counter_stats_reply",
Rich Lanea06d0c32013-03-25 08:52:03 -0700494]
495
496stats_request_list = [
497 "of_aggregate_stats_request",
498 "of_desc_stats_request",
499 "of_experimenter_stats_request",
500 "of_flow_stats_request",
501 "of_group_stats_request",
502 "of_group_desc_stats_request",
503 "of_group_features_stats_request",
504 "of_meter_stats_request",
505 "of_meter_config_stats_request",
506 "of_meter_features_stats_request",
507 "of_port_stats_request",
508 "of_port_desc_stats_request",
509 "of_queue_stats_request",
510 "of_table_stats_request",
Rich Lane353a79f2013-11-13 10:39:56 -0800511 "of_table_features_stats_request",
512 "of_bsn_stats_request",
513 "of_bsn_lacp_stats_request",
Wilson Ng27e4beb2013-12-03 12:33:01 -0800514 "of_bsn_switch_pipeline_stats_request",
xinwu358e6162013-12-04 16:49:48 -0800515 "of_bsn_port_counter_stats_request",
516 "of_bsn_vlan_counter_stats_request",
Rich Lanea06d0c32013-03-25 08:52:03 -0700517]
518
519flow_mod_list = [
520 "of_flow_add",
521 "of_flow_modify",
522 "of_flow_modify_strict",
523 "of_flow_delete",
524 "of_flow_delete_strict"
525]
526
Rob Vaterlausb3f49d92013-10-01 17:57:31 -0700527error_msg_list = [
528 "of_hello_failed_error_msg",
529 "of_bad_request_error_msg",
530 "of_bad_action_error_msg",
531 "of_bad_instruction_error_msg",
532 "of_bad_match_error_msg",
533 "of_flow_mod_failed_error_msg",
534 "of_group_mod_failed_error_msg",
535 "of_port_mod_failed_error_msg",
536 "of_table_mod_failed_error_msg",
537 "of_queue_op_failed_error_msg",
538 "of_switch_config_failed_error_msg",
539 "of_role_request_failed_error_msg",
540 "of_meter_mod_failed_error_msg",
541 "of_table_features_failed_error_msg",
542 "of_experimenter_error_msg"
543]
544
Rich Lanee3113672013-12-06 17:09:57 -0800545group_mod_list = [
546 "of_group_add",
547 "of_group_modify",
548 "of_group_delete",
549]
550
Rich Lanea06d0c32013-03-25 08:52:03 -0700551def sub_class_map(base_type, version):
552 """
553 Returns an iterable object giving the instance nameys and subclass types
554 for the base_type, version values
555 """
556 rv = []
557 if base_type not in inheritance_map:
558 return rv
559
560 for instance in inheritance_map[base_type]:
561 subcls = loxi_utils.instance_to_class(instance, base_type)
562 if not loxi_utils.class_in_version(subcls, version):
563 continue
564 rv.append((instance, subcls))
565
566 return rv
567
568################################################################
569#
570# Extension related data and functions
571#
572################################################################
573
574# Per OF Version, per experimenter, map exp msg type (subtype) to object IDs
575# @fixme Generate defines for OF_<exp>_SUBTYPE_<msg> for the values below?
576extension_message_subtype = {
577 # version 1.0
578 of_g.VERSION_1_0:dict( # Version 1.0 extensions
579 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700580 },
581 nicira = { # Nicira extensions, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700582 },
583 ),
584 of_g.VERSION_1_1:dict( # Version 1.0 extensions
585 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700586 },
587 ),
588 of_g.VERSION_1_2:dict( # Version 1.0 extensions
589 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700590 },
591 ),
592 of_g.VERSION_1_3:dict( # Version 1.0 extensions
593 bsn = { # BSN extensions; indexed by class name, value is subtype
Rich Lanea06d0c32013-03-25 08:52:03 -0700594 },
595 ),
596}
597
598# Set to empty dict if no extension actions defined
599# Per OF Version, per experimenter, map actions to subtype
600extension_action_subtype = {
601 # version 1.0
602 of_g.VERSION_1_0:dict( # Version 1.0 extensions
603 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700604 },
605 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700606 }
607 ),
608 of_g.VERSION_1_1:dict( # Version 1.0 extensions
609 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700610 },
611 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700612 }
613 ),
614 of_g.VERSION_1_2:dict( # Version 1.0 extensions
615 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700616 },
617 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700618 }
619 ),
620 of_g.VERSION_1_3:dict( # Version 1.0 extensions
621 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700622 },
623 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700624 }
625 ),
626}
627
628# Set to empty dict if no extension actions defined
629# Per OF Version, per experimenter, map actions to subtype
630extension_action_id_subtype = {
631 # version 1.0
632 of_g.VERSION_1_0:dict(),
633 of_g.VERSION_1_1:dict(),
634 of_g.VERSION_1_2:dict(),
635 of_g.VERSION_1_3:dict( # Version 1.3 extensions
636 bsn = { # of_action_bsn_
Rich Lanea06d0c32013-03-25 08:52:03 -0700637 },
638 nicira = { # of_action_nicira_
Rich Lanea06d0c32013-03-25 08:52:03 -0700639 }
640 ),
641}
642
643# Set to empty dict if no extension instructions defined
Rich Laneef7b9942013-11-18 16:29:28 -0800644extension_instruction_subtype = {
645 # version 1.0
646 of_g.VERSION_1_0:dict(),
647 of_g.VERSION_1_1:dict(),
648 of_g.VERSION_1_2:dict(),
649 of_g.VERSION_1_3:dict(
650 bsn = { # of_instruction_bsn_
651 },
652 nicira = { # of_instruction_nicira_
653 }
654 ),
655}
Rich Lanea06d0c32013-03-25 08:52:03 -0700656
657# Set to empty dict if no extension instructions defined
658extension_queue_prop_subtype = {}
659
660# Set to empty dict if no extension instructions defined
661extension_table_feature_prop_subtype = {}
662
663extension_objects = [
664 extension_message_subtype,
665 extension_action_subtype,
666 extension_action_id_subtype,
667 extension_instruction_subtype,
668 extension_queue_prop_subtype,
669 extension_table_feature_prop_subtype
670]
671
672################################################################
673# These are extension type generic (for messages, actions...)
674################################################################
675
676def extension_to_experimenter_name(cls):
677 """
678 Return the name of the experimenter if class is an
679 extension, else None
680
681 This is brute force; we search all extension data for a match
682 """
Andreas Wundsam53256162013-05-02 14:05:53 -0700683
Rich Lanea06d0c32013-03-25 08:52:03 -0700684 for ext_obj in extension_objects:
685 for version, exp_list in ext_obj.items():
686 for exp_name, classes in exp_list.items():
687 if cls in classes:
688 return exp_name
689 return None
690
691def extension_to_experimenter_id(cls):
692 """
693 Return the ID of the experimenter if class is an
694 extension, else None
695 """
696 exp_name = extension_to_experimenter_name(cls)
697 if exp_name:
698 return of_g.experimenter_name_to_id[exp_name]
699 return None
700
701def extension_to_experimenter_macro_name(cls):
702 """
703 Return the "macro name" of the ID of the experimenter if class is an
704 extension, else None
705 """
706 exp_name = extension_to_experimenter_name(cls)
707 if exp_name:
708 return "OF_EXPERIMENTER_ID_" + exp_name.upper()
709 return None
710
711def extension_to_subtype(cls, version):
712 """
713 Generic across all extension objects, return subtype identifier
714 """
715 for ext_obj in extension_objects:
716 for version, exp_list in ext_obj.items():
717 for exp_name, classes in exp_list.items():
718 if cls in classes:
719 return classes[cls]
720
721def class_is_extension(cls, version):
722 """
723 Return True if class, version is recognized as an extension
724 of any type (message, action....)
725
726 Accepts of_g.OF_VERSION_ANY
727 """
728
729 for ext_obj in extension_objects:
730 if cls_is_ext_obj(cls, version, ext_obj):
731 return True
732
733 return False
734
735# Internal
736def cls_is_ext_obj(cls, version, ext_obj):
737 """
738 @brief Return True if cls in an extension of type ext_obj
739 @param cls The class to check
740 @param version The version to check
741 @param ext_obj The extension object dictionary (messages, actions...)
742
743 Accepts of_g.VERSION_ANY
744 """
745
746 # Call with each version if "any" is passed
747 if version == of_g.VERSION_ANY:
748 for v in of_g.of_version_range:
749 if cls_is_ext_obj(cls, v, ext_obj):
750 return True
751 else: # Version specified
752 if version in ext_obj:
753 for exp, subtype_vals in ext_obj[version].items():
754 if cls in subtype_vals:
755 return True
756
757 return False
Andreas Wundsam53256162013-05-02 14:05:53 -0700758
Rich Lanea06d0c32013-03-25 08:52:03 -0700759################################################################
760# These are extension message specific
761################################################################
762
763def message_is_extension(cls, version):
764 """
765 Return True if cls, version is recognized as an extension
766 This is brute force, searching records for a match
767 """
768 return cls_is_ext_obj(cls, version, extension_message_subtype)
769
770def extension_message_to_subtype(cls, version):
771 """
772 Return the subtype of the experimenter message if the class is an
773 extension, else None
774 """
775 if version in extension_message_subtype:
776 for exp, classes in extension_message_subtype[version].items():
777 for ext_class, subtype in classes.items():
778 if cls == ext_class:
779 return subtype
780 return None
781
782################################################################
783# These are extension action specific
784################################################################
785
786def action_is_extension(cls, version):
787 """
788 Return True if cls, version is recognized as an action extension
789 This is brute force, searching records for a match
790 """
791 return cls_is_ext_obj(cls, version, extension_action_subtype)
792
793def extension_action_to_subtype(cls, version):
794 """
795 Return the ID of the action subtype (for its experimenteer)
796 if class is an action extension, else None
797 """
798 if version in extension_action_subtype:
799 for exp, classes in extension_action_subtype[version].items():
800 if cls in classes:
801 return classes[cls]
802
803 return None
804
805################################################################
806# These are extension action specific
807################################################################
808
809def action_id_is_extension(cls, version):
810 """
811 Return True if cls, version is recognized as an action ID extension
812 This is brute force, searching records for a match
813 """
814 if version not in [of_g.VERSION_1_3]: # Action IDs only 1.3
815 return False
816 return cls_is_ext_obj(cls, version, extension_action_id_subtype)
817
818def extension_action_id_to_subtype(cls, version):
819 """
820 Return the ID of the action ID subtype (for its experimenteer)
821 if class is an action ID extension, else None
822 """
823 if version in extension_action_id_subtype:
824 for exp, classes in extension_action_id_subtype[version].items():
825 if cls in classes:
826 return classes[cls]
827
828 return None
829
830################################################################
831# These are extension instruction specific
832################################################################
833
834def instruction_is_extension(cls, version):
835 """
836 Return True if cls, version is recognized as an instruction extension
837 This is brute force, searching records for a match
838 """
839 return cls_is_ext_obj(cls, version, extension_instruction_subtype)
840
841################################################################
842# These are extension queue_prop specific
843################################################################
844
845def queue_prop_is_extension(cls, version):
846 """
847 Return True if cls, version is recognized as an instruction extension
848 This is brute force, searching records for a match
849 """
850 return cls_is_ext_obj(cls, version, extension_queue_prop_subtype)
851
852################################################################
853# These are extension table_feature_prop specific
854################################################################
855
856def table_feature_prop_is_extension(cls, version):
857 """
858 Return True if cls, version is recognized as an instruction extension
859 This is brute force, searching records for a match
860 """
861 return cls_is_ext_obj(cls, version,
862 extension_table_feature_prop_subtype)