blob: 5f58eb3aa68e522f8767297da9b0cda572c661a0 [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
36import of_g
37import sys
38from generic_utils import *
39import oxm
40import loxi_utils.loxi_utils as loxi_utils
41
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 = {
57 # version 1.0
58 of_g.VERSION_1_0:dict(),
59
60 # version 1.1
61 of_g.VERSION_1_1:dict(
62 goto_table = 1,
63 write_metadata = 2,
64 write_actions = 3,
65 apply_actions = 4,
66 clear_actions = 5,
67 experimenter = 0xffff
68 ),
69
70 # version 1.2
71 of_g.VERSION_1_2:dict(
72 goto_table = 1,
73 write_metadata = 2,
74 write_actions = 3,
75 apply_actions = 4,
76 clear_actions = 5,
77 experimenter = 0xffff
78 ),
79
80 # version 1.3
81 of_g.VERSION_1_3:dict(
82 goto_table = 1,
83 write_metadata = 2,
84 write_actions = 3,
85 apply_actions = 4,
86 clear_actions = 5,
87 meter = 6,
88 experimenter = 0xffff
89 )
90 }
91
92of_1_3_action_types = dict(
93 output = 0,
94 copy_ttl_out = 11,
95 copy_ttl_in = 12,
96 set_mpls_ttl = 15,
97 dec_mpls_ttl = 16,
98 push_vlan = 17,
99 pop_vlan = 18,
100 push_mpls = 19,
101 pop_mpls = 20,
102 set_queue = 21,
103 group = 22,
104 set_nw_ttl = 23,
105 dec_nw_ttl = 24,
106 set_field = 25,
107 push_pbb = 26,
108 pop_pbb = 27,
109 experimenter = 0xffff,
110 bsn_mirror = 0xffff,
111 bsn_set_tunnel_dst = 0xffff,
112 nicira_dec_ttl = 0xffff
113 )
114
115# Indexed by OF version
116action_types = {
117 # version 1.0
118 of_g.VERSION_1_0:dict(
119 output = 0,
120 set_vlan_vid = 1,
121 set_vlan_pcp = 2,
122 strip_vlan = 3,
123 set_dl_src = 4,
124 set_dl_dst = 5,
125 set_nw_src = 6,
126 set_nw_dst = 7,
127 set_nw_tos = 8,
128 set_tp_src = 9,
129 set_tp_dst = 10,
130 enqueue = 11,
131 experimenter = 0xffff,
132 bsn_mirror = 0xffff,
133 bsn_set_tunnel_dst = 0xffff,
134 nicira_dec_ttl = 0xffff
135 ),
136
137 # version 1.1
138 of_g.VERSION_1_1:dict(
139 output = 0,
140 set_vlan_vid = 1,
141 set_vlan_pcp = 2,
142 set_dl_src = 3,
143 set_dl_dst = 4,
144 set_nw_src = 5,
145 set_nw_dst = 6,
146 set_nw_tos = 7,
147 set_nw_ecn = 8,
148 set_tp_src = 9,
149 set_tp_dst = 10,
150 copy_ttl_out = 11,
151 copy_ttl_in = 12,
152 set_mpls_label = 13,
153 set_mpls_tc = 14,
154 set_mpls_ttl = 15,
155 dec_mpls_ttl = 16,
156 push_vlan = 17,
157 pop_vlan = 18,
158 push_mpls = 19,
159 pop_mpls = 20,
160 set_queue = 21,
161 group = 22,
162 set_nw_ttl = 23,
163 dec_nw_ttl = 24,
164 experimenter = 0xffff,
165 bsn_mirror = 0xffff,
166 bsn_set_tunnel_dst = 0xffff,
167 nicira_dec_ttl = 0xffff
168 ),
169
170 # version 1.2
171 of_g.VERSION_1_2:dict(
172 output = 0,
173 copy_ttl_out = 11,
174 copy_ttl_in = 12,
175 set_mpls_ttl = 15,
176 dec_mpls_ttl = 16,
177 push_vlan = 17,
178 pop_vlan = 18,
179 push_mpls = 19,
180 pop_mpls = 20,
181 set_queue = 21,
182 group = 22,
183 set_nw_ttl = 23,
184 dec_nw_ttl = 24,
185 set_field = 25,
186 experimenter = 0xffff,
187 bsn_mirror = 0xffff,
188 bsn_set_tunnel_dst = 0xffff,
189 nicira_dec_ttl = 0xffff
190 ),
191
192 # version 1.3
193 of_g.VERSION_1_3:of_1_3_action_types
194
195 }
196
197action_id_types = {
198 # version 1.0
199 of_g.VERSION_1_0:dict(),
200 of_g.VERSION_1_1:dict(),
201 of_g.VERSION_1_2:dict(),
202 of_g.VERSION_1_3:of_1_3_action_types
203 }
204
205queue_prop_types = {
206 # version 1.0
207 of_g.VERSION_1_0:dict(
208 min_rate = 1,
209 # experimenter = 0xffff
210 ),
211 # version 1.1
212 of_g.VERSION_1_1:dict(
213 min_rate = 1,
214 # experimenter = 0xffff
215 ),
216 # version 1.2
217 of_g.VERSION_1_2:dict(
218 min_rate = 1,
219 max_rate = 2,
220 experimenter = 0xffff
221 ),
222 # version 1.3
223 of_g.VERSION_1_3:dict(
224 min_rate = 1,
225 max_rate = 2,
226 experimenter = 0xffff
227 )
228 }
229
230oxm_types = {
231 # version 1.0
232 of_g.VERSION_1_0:dict(),
233
234 # version 1.1
235 of_g.VERSION_1_1:dict(),
236
237 # version 1.2
238 of_g.VERSION_1_2:oxm.oxm_wire_type,
239
240 # version 1.3
241 of_g.VERSION_1_3:oxm.oxm_wire_type # FIXME needs update for 1.3?
242 }
243
244hello_elem_types = {
245 # version 1.0
246 of_g.VERSION_1_0:dict(),
247
248 # version 1.1
249 of_g.VERSION_1_1:dict(),
250
251 # version 1.2
252 of_g.VERSION_1_2:dict(),
253
254 # version 1.3
255 of_g.VERSION_1_3:dict(
256 versionbitmap = 1
257 )
258 }
259
260table_feature_prop_types = {
261 # version 1.0
262 of_g.VERSION_1_0:dict(),
263
264 # version 1.1
265 of_g.VERSION_1_1:dict(),
266
267 # version 1.2
268 of_g.VERSION_1_2:dict(),
269
270 # version 1.3
271 of_g.VERSION_1_3:dict(
272 instructions = 0,
273 instructions_miss = 1,
274 next_tables = 2,
275 next_tables_miss = 3,
276 write_actions = 4,
277 write_actions_miss = 5,
278 apply_actions = 6,
279 apply_actions_miss = 7,
280 match = 8,
281 wildcards = 10,
282 write_setfield = 12,
283 write_setfield_miss = 13,
284 apply_setfield = 14,
285 apply_setfield_miss = 15,
286# experimenter = 0xFFFE,
287# experimenter_miss = 0xFFFF,
288 experimenter = 0xFFFF, # Wrong: should be experimenter_miss
289 )
290 }
291
292meter_band_types = {
293 # version 1.0
294 of_g.VERSION_1_0:dict(),
295
296 # version 1.1
297 of_g.VERSION_1_1:dict(),
298
299 # version 1.2
300 of_g.VERSION_1_2:dict(),
301
302 # version 1.3
303 of_g.VERSION_1_3:dict(
304 drop = 1,
305 dscp_remark = 2,
306 experimenter = 0xFFFF,
307 )
308 }
309
310# All inheritance data for non-messages
311inheritance_data = dict(
312 of_instruction = instruction_types,
313 of_action = action_types,
314 of_action_id = action_id_types,
315 of_oxm = oxm_types,
316 of_queue_prop = queue_prop_types,
317 of_hello_elem = hello_elem_types,
318 of_table_feature_prop = table_feature_prop_types,
319 of_meter_band = meter_band_types
320 )
321
322################################################################
323# Now generate the maps from parent to list of subclasses
324################################################################
325
326# # These lists have entries which are a fixed type, no inheritance
327# fixed_lists = [
328# "of_list_bucket",
329# "of_list_bucket_counter",
330# "of_list_flow_stats_entry",
331# "of_list_group_desc_stats_entry",
332# "of_list_group_stats_entry",
333# "of_list_packet_queue",
334# "of_list_port_desc",
335# "of_list_port_stats_entry",
336# "of_list_queue_stats_entry",
337# "of_list_table_stats_entry"
338# ]
339
340# for cls in fixed_lists:
341# base_type = list_to_entry_type(cls)
342# of_g.inheritance_map[base_type] = [base_type]
343
344inheritance_map = dict()
345for parent, versioned in inheritance_data.items():
346 inheritance_map[parent] = set()
347 for ver, subclasses in versioned.items():
348 for subcls in subclasses:
349 inheritance_map[parent].add(subcls)
350
351def class_is_virtual(cls):
352 """
353 Returns True if cls is a virtual class
354 """
355 if cls in inheritance_map:
356 return True
357 if cls.find("header") > 0:
358 return True
359 if loxi_utils.class_is_list(cls):
360 return True
361 return False
362
363################################################################
364#
365# These are message types
366#
367################################################################
368
369message_types = {
370 # version 1.0
371 of_g.VERSION_1_0:dict(
372 hello = 0,
373 error_msg = 1,
374 echo_request = 2,
375 echo_reply = 3,
376 experimenter = 4,
377 features_request = 5,
378 features_reply = 6,
379 get_config_request = 7,
380 get_config_reply = 8,
381 set_config = 9,
382 packet_in = 10,
383 flow_removed = 11,
384 port_status = 12,
385 packet_out = 13,
386 flow_mod = 14,
387 port_mod = 15,
388 stats_request = 16,
389 stats_reply = 17,
390 barrier_request = 18,
391 barrier_reply = 19,
392 queue_get_config_request = 20,
393 queue_get_config_reply = 21,
394 table_mod = 22 # Unofficial 1.0 extension
395 ),
396
397 # version 1.1
398 of_g.VERSION_1_1:dict(
399 hello = 0,
400 error_msg = 1,
401 echo_request = 2,
402 echo_reply = 3,
403 experimenter = 4,
404 features_request = 5,
405 features_reply = 6,
406 get_config_request = 7,
407 get_config_reply = 8,
408 set_config = 9,
409 packet_in = 10,
410 flow_removed = 11,
411 port_status = 12,
412 packet_out = 13,
413 flow_mod = 14,
414 group_mod = 15,
415 port_mod = 16,
416 table_mod = 17,
417 stats_request = 18,
418 stats_reply = 19,
419 barrier_request = 20,
420 barrier_reply = 21,
421 queue_get_config_request = 22,
422 queue_get_config_reply = 23
423 ),
424
425 # version 1.2
426 of_g.VERSION_1_2:dict(
427 hello = 0,
428 error_msg = 1,
429 echo_request = 2,
430 echo_reply = 3,
431 experimenter = 4,
432 features_request = 5,
433 features_reply = 6,
434 get_config_request = 7,
435 get_config_reply = 8,
436 set_config = 9,
437 packet_in = 10,
438 flow_removed = 11,
439 port_status = 12,
440 packet_out = 13,
441 flow_mod = 14,
442 group_mod = 15,
443 port_mod = 16,
444 table_mod = 17,
445 stats_request = 18,
446 stats_reply = 19,
447 barrier_request = 20,
448 barrier_reply = 21,
449 queue_get_config_request = 22,
450 queue_get_config_reply = 23,
451 role_request = 24,
452 role_reply = 25,
453 ),
454
455 # version 1.3
456 of_g.VERSION_1_3:dict(
457 hello = 0,
458 error_msg = 1,
459 echo_request = 2,
460 echo_reply = 3,
461 experimenter = 4,
462 features_request = 5,
463 features_reply = 6,
464 get_config_request = 7,
465 get_config_reply = 8,
466 set_config = 9,
467 packet_in = 10,
468 flow_removed = 11,
469 port_status = 12,
470 packet_out = 13,
471 flow_mod = 14,
472 group_mod = 15,
473 port_mod = 16,
474 table_mod = 17,
475 stats_request = 18, # FIXME Multipart
476 stats_reply = 19,
477 barrier_request = 20,
478 barrier_reply = 21,
479 queue_get_config_request = 22,
480 queue_get_config_reply = 23,
481 role_request = 24,
482 role_reply = 25,
483 async_get_request = 26,
484 async_get_reply = 27,
485 async_set = 28,
486 meter_mod = 29
487 )
488 }
489
490################################################################
491#
492# These are other objects that have a notion of type but are
493# not (yet) promoted to objects with inheritance
494#
495################################################################
496
497stats_types = {
498 # version 1.0
499 of_g.VERSION_1_0:dict(
500 desc = 0,
501 flow = 1,
502 aggregate = 2,
503 table = 3,
504 port = 4,
505 queue = 5,
506 experimenter = 0xffff
507 ),
508
509 # version 1.1
510 of_g.VERSION_1_1:dict(
511 desc = 0,
512 flow = 1,
513 aggregate = 2,
514 table = 3,
515 port = 4,
516 queue = 5,
517 group = 6,
518 group_desc = 7,
519 experimenter = 0xffff
520 ),
521
522 # version 1.2
523 of_g.VERSION_1_2:dict(
524 desc = 0,
525 flow = 1,
526 aggregate = 2,
527 table = 3,
528 port = 4,
529 queue = 5,
530 group = 6,
531 group_desc = 7,
532 group_features = 8,
533 experimenter = 0xffff
534 ),
535
536 # version 1.3
537 of_g.VERSION_1_3:dict(
538 desc = 0,
539 flow = 1,
540 aggregate = 2,
541 table = 3,
542 port = 4,
543 queue = 5,
544 group = 6,
545 group_desc = 7,
546 group_features = 8,
547 meter = 9,
548 meter_config = 10,
549 meter_features = 11,
550 table_features = 12,
551 port_desc = 13,
552 experimenter = 0xffff
553 )
554 }
555
556common_flow_mod_types = dict(
557 add = 0,
558 modify = 1,
559 modify_strict = 2,
560 delete = 3,
561 delete_strict = 4
562 )
563
564flow_mod_types = {
565 # version 1.0
566 of_g.VERSION_1_0:common_flow_mod_types,
567 of_g.VERSION_1_1:common_flow_mod_types,
568 of_g.VERSION_1_2:common_flow_mod_types,
569 of_g.VERSION_1_3:common_flow_mod_types
570 }
571
572# These do not translate to objects (yet)
573error_types = {
574 # version 1.0
575 of_g.VERSION_1_0:dict(
576 hello_failed = 0,
577 bad_request = 1,
578 bad_action = 2,
579 flow_mod_failed = 3,
580 port_mod_failed = 4,
581 queue_op_failed = 5
582 ),
583
584 # version 1.1
585 of_g.VERSION_1_1:dict(
586 hello_failed = 0,
587 bad_request = 1,
588 bad_action = 2,
589 bad_instruction = 3,
590 bad_match = 4,
591 flow_mod_failed = 5,
592 group_mod_failed = 6,
593 port_mod_failed = 7,
594 table_mod_failed = 8,
595 queue_op_failed = 9,
596 switch_config_failed = 10
597 ),
598
599 # version 1.2
600 of_g.VERSION_1_2:dict(
601 hello_failed = 0,
602 bad_request = 1,
603 bad_action = 2,
604 bad_instruction = 3,
605 bad_match = 4,
606 flow_mod_failed = 5,
607 group_mod_failed = 6,
608 port_mod_failed = 7,
609 table_mod_failed = 8,
610 queue_op_failed = 9,
611 switch_config_failed = 10,
612 role_request_failed = 11,
613 experimenter = 0xffff
614 ),
615
616 # version 1.3
617 of_g.VERSION_1_3:dict(
618 hello_failed = 0,
619 bad_request = 1,
620 bad_action = 2,
621 bad_instruction = 3,
622 bad_match = 4,
623 flow_mod_failed = 5,
624 group_mod_failed = 6,
625 port_mod_failed = 7,
626 table_mod_failed = 8,
627 queue_op_failed = 9,
628 switch_config_failed = 10,
629 role_request_failed = 11,
630 meter_mod_failed = 12,
631 table_features_failed= 13,
632 experimenter = 0xffff
633 )
634 }
635
636##
637# These are the objects whose length is specified by an external
638# reference, specifically another data member in the class.
Andreas Wundsam53256162013-05-02 14:05:53 -0700639#
Rich Lanea06d0c32013-03-25 08:52:03 -0700640#external_length_spec = {
641# ("of_packet_out", "actions", OF_VERSION_1_0) : "actions_len",
642# ("of_packet_out", "actions", OF_VERSION_1_1) : "actions_len",
643# ("of_packet_out", "actions", OF_VERSION_1_2) : "actions_len",
644# ("of_packet_out", "actions", OF_VERSION_1_3) : "actions_len"
645#}
646
647
648################################################################
649#
Andreas Wundsam53256162013-05-02 14:05:53 -0700650# type_val is the primary data structure that maps an
Rich Lanea06d0c32013-03-25 08:52:03 -0700651# (class_name, version) pair to the wire data type value
652#
653################################################################
654
655type_val = dict()
656
657for version, classes in message_types.items():
658 for cls in classes:
659 name = "of_" + cls
660 type_val[(name, version)] = classes[cls]
661
662for parent, versioned in inheritance_data.items():
663 for version, subclasses in versioned.items():
664 for subcls, value in subclasses.items():
665 name = parent + "_" + subcls
666 type_val[(name, version)] = value
667
668# Special case OF-1.2 match type
669type_val[("of_match_v3", of_g.VERSION_1_2)] = 0x8000
670type_val[("of_match_v3", of_g.VERSION_1_3)] = 0x8000
671
672# Utility function
673def dict_to_array(d, m_val, def_val=-1):
674 """
675 Given a dictionary, d, with each value a small integer,
676 produce an array indexed by the integer whose value is the key.
677 @param d The dictionary
678 @param m_val Ignore values greater than m_val
679 @param def_val The default value (for indices not in range of d)
680 """
681
682 # Get the max value in range for hash
683 max_val = 0
684 for key in d:
685 if (d[key] > max_val) and (d[key] < m_val):
686 max_val = d[key]
687 ar = []
688 for x in range(0, max_val + 1):
689 ar.append(def_val)
690 for key in d:
691 if (d[key] < m_val):
692 ar[d[key]] = key
693 return ar
694
695def type_array_len(version_indexed, max_val):
696 """
697 Given versioned information about a type, calculate how long
698 the unified array should be.
699
Andreas Wundsam53256162013-05-02 14:05:53 -0700700 @param version_indexed A dict indexed by version. Each value is a
Rich Lanea06d0c32013-03-25 08:52:03 -0700701 dict indexed by a name and whose value is an integer
702 @param max_val Ignore values greater than this for length calcs
703 """
704 # First, find the max length of all arrays
705 arr_len = 0
706 for version, val_dict in version_indexed.items():
707 ar = dict_to_array(val_dict, max_val, invalid_type)
708 if arr_len < len(ar):
709 arr_len = len(ar)
710 return arr_len
711
712# FIXME: Need to move update for multipart messages
713
714stats_reply_list = [
715 "of_aggregate_stats_reply",
716 "of_desc_stats_reply",
717 "of_experimenter_stats_reply",
718 "of_flow_stats_reply",
719 "of_group_stats_reply",
720 "of_group_desc_stats_reply",
721 "of_group_features_stats_reply",
722 "of_meter_stats_reply",
723 "of_meter_config_stats_reply",
724 "of_meter_features_stats_reply",
725 "of_port_stats_reply",
726 "of_port_desc_stats_reply",
727 "of_queue_stats_reply",
728 "of_table_stats_reply",
729 "of_table_features_stats_reply"
730]
731
732stats_request_list = [
733 "of_aggregate_stats_request",
734 "of_desc_stats_request",
735 "of_experimenter_stats_request",
736 "of_flow_stats_request",
737 "of_group_stats_request",
738 "of_group_desc_stats_request",
739 "of_group_features_stats_request",
740 "of_meter_stats_request",
741 "of_meter_config_stats_request",
742 "of_meter_features_stats_request",
743 "of_port_stats_request",
744 "of_port_desc_stats_request",
745 "of_queue_stats_request",
746 "of_table_stats_request",
747 "of_table_features_stats_request"
748]
749
750flow_mod_list = [
751 "of_flow_add",
752 "of_flow_modify",
753 "of_flow_modify_strict",
754 "of_flow_delete",
755 "of_flow_delete_strict"
756]
757
758def sub_class_map(base_type, version):
759 """
760 Returns an iterable object giving the instance nameys and subclass types
761 for the base_type, version values
762 """
763 rv = []
764 if base_type not in inheritance_map:
765 return rv
766
767 for instance in inheritance_map[base_type]:
768 subcls = loxi_utils.instance_to_class(instance, base_type)
769 if not loxi_utils.class_in_version(subcls, version):
770 continue
771 rv.append((instance, subcls))
772
773 return rv
774
775################################################################
776#
777# Extension related data and functions
778#
779################################################################
780
781# Per OF Version, per experimenter, map exp msg type (subtype) to object IDs
782# @fixme Generate defines for OF_<exp>_SUBTYPE_<msg> for the values below?
783extension_message_subtype = {
784 # version 1.0
785 of_g.VERSION_1_0:dict( # Version 1.0 extensions
786 bsn = { # BSN extensions; indexed by class name, value is subtype
787 "of_bsn_set_ip_mask" : 0,
788 "of_bsn_get_ip_mask_request" : 1,
789 "of_bsn_get_ip_mask_reply" : 2,
790 "of_bsn_set_mirroring" : 3,
791 "of_bsn_get_mirroring_request" : 4,
792 "of_bsn_get_mirroring_reply" : 5,
793 "of_bsn_shell_command" : 6,
794 "of_bsn_shell_output" : 7,
795 "of_bsn_shell_status" : 8,
796 "of_bsn_get_interfaces_request" : 9,
797 "of_bsn_get_interfaces_reply" : 10,
Rich Lanefd2fcd52013-03-28 09:18:31 -0700798 "of_bsn_set_pktin_suppression" : 11,
Ken Chiang103e1472013-05-13 17:21:57 -0700799 "of_bsn_set_l2_table" : 12,
800 "of_bsn_get_l2_table_request" : 13,
801 "of_bsn_get_l2_table_reply" : 14,
Rich Lanea06d0c32013-03-25 08:52:03 -0700802 },
803 nicira = { # Nicira extensions, value is subtype
804 "of_nicira_controller_role_request" : 10,
805 "of_nicira_controller_role_reply" : 11,
806 },
807 ),
808 of_g.VERSION_1_1:dict( # Version 1.0 extensions
809 bsn = { # BSN extensions; indexed by class name, value is subtype
810 "of_bsn_set_mirroring" : 3,
811 "of_bsn_get_mirroring_request" : 4,
812 "of_bsn_get_mirroring_reply" : 5,
813 "of_bsn_get_interfaces_request" : 9,
814 "of_bsn_get_interfaces_reply" : 10,
Rich Lanefd2fcd52013-03-28 09:18:31 -0700815 "of_bsn_set_pktin_suppression" : 11,
Rich Lanea06d0c32013-03-25 08:52:03 -0700816 },
817 ),
818 of_g.VERSION_1_2:dict( # Version 1.0 extensions
819 bsn = { # BSN extensions; indexed by class name, value is subtype
820 "of_bsn_set_mirroring" : 3,
821 "of_bsn_get_mirroring_request" : 4,
822 "of_bsn_get_mirroring_reply" : 5,
823 "of_bsn_get_interfaces_request" : 9,
824 "of_bsn_get_interfaces_reply" : 10,
Rich Lanefd2fcd52013-03-28 09:18:31 -0700825 "of_bsn_set_pktin_suppression" : 11,
Rich Lanea06d0c32013-03-25 08:52:03 -0700826 },
827 ),
828 of_g.VERSION_1_3:dict( # Version 1.0 extensions
829 bsn = { # BSN extensions; indexed by class name, value is subtype
830 "of_bsn_set_mirroring" : 3,
831 "of_bsn_get_mirroring_request" : 4,
832 "of_bsn_get_mirroring_reply" : 5,
833 "of_bsn_get_interfaces_request" : 9,
834 "of_bsn_get_interfaces_reply" : 10,
Rich Lanefd2fcd52013-03-28 09:18:31 -0700835 "of_bsn_set_pktin_suppression" : 11,
Rich Lanea06d0c32013-03-25 08:52:03 -0700836 },
837 ),
838}
839
840# Set to empty dict if no extension actions defined
841# Per OF Version, per experimenter, map actions to subtype
842extension_action_subtype = {
843 # version 1.0
844 of_g.VERSION_1_0:dict( # Version 1.0 extensions
845 bsn = { # of_action_bsn_
846 "of_action_bsn_mirror" : 1,
847 "of_action_bsn_set_tunnel_dst" : 2,
848 },
849 nicira = { # of_action_nicira_
850 "of_action_nicira_dec_ttl" : 18,
851 }
852 ),
853 of_g.VERSION_1_1:dict( # Version 1.0 extensions
854 bsn = { # of_action_bsn_
855 "of_action_bsn_mirror" : 1,
856 "of_action_bsn_set_tunnel_dst" : 2,
857 },
858 nicira = { # of_action_nicira_
859 "of_action_nicira_dec_ttl" : 18,
860 }
861 ),
862 of_g.VERSION_1_2:dict( # Version 1.0 extensions
863 bsn = { # of_action_bsn_
864 "of_action_bsn_mirror" : 1,
865 "of_action_bsn_set_tunnel_dst" : 2,
866 },
867 nicira = { # of_action_nicira_
868 "of_action_nicira_dec_ttl" : 18,
869 }
870 ),
871 of_g.VERSION_1_3:dict( # Version 1.0 extensions
872 bsn = { # of_action_bsn_
873 "of_action_bsn_mirror" : 1,
874 "of_action_bsn_set_tunnel_dst" : 2,
875 },
876 nicira = { # of_action_nicira_
877 "of_action_nicira_dec_ttl" : 18,
878 }
879 ),
880}
881
882# Set to empty dict if no extension actions defined
883# Per OF Version, per experimenter, map actions to subtype
884extension_action_id_subtype = {
885 # version 1.0
886 of_g.VERSION_1_0:dict(),
887 of_g.VERSION_1_1:dict(),
888 of_g.VERSION_1_2:dict(),
889 of_g.VERSION_1_3:dict( # Version 1.3 extensions
890 bsn = { # of_action_bsn_
891 "of_action_id_bsn_mirror" : 1,
892 "of_action_id_bsn_set_tunnel_dst" : 2,
893 },
894 nicira = { # of_action_nicira_
895 "of_action_id_nicira_dec_ttl" : 18,
896 }
897 ),
898}
899
900# Set to empty dict if no extension instructions defined
901extension_instruction_subtype = {}
902
903# Set to empty dict if no extension instructions defined
904extension_queue_prop_subtype = {}
905
906# Set to empty dict if no extension instructions defined
907extension_table_feature_prop_subtype = {}
908
909extension_objects = [
910 extension_message_subtype,
911 extension_action_subtype,
912 extension_action_id_subtype,
913 extension_instruction_subtype,
914 extension_queue_prop_subtype,
915 extension_table_feature_prop_subtype
916]
917
918################################################################
919# These are extension type generic (for messages, actions...)
920################################################################
921
922def extension_to_experimenter_name(cls):
923 """
924 Return the name of the experimenter if class is an
925 extension, else None
926
927 This is brute force; we search all extension data for a match
928 """
Andreas Wundsam53256162013-05-02 14:05:53 -0700929
Rich Lanea06d0c32013-03-25 08:52:03 -0700930 for ext_obj in extension_objects:
931 for version, exp_list in ext_obj.items():
932 for exp_name, classes in exp_list.items():
933 if cls in classes:
934 return exp_name
935 return None
936
937def extension_to_experimenter_id(cls):
938 """
939 Return the ID of the experimenter if class is an
940 extension, else None
941 """
942 exp_name = extension_to_experimenter_name(cls)
943 if exp_name:
944 return of_g.experimenter_name_to_id[exp_name]
945 return None
946
947def extension_to_experimenter_macro_name(cls):
948 """
949 Return the "macro name" of the ID of the experimenter if class is an
950 extension, else None
951 """
952 exp_name = extension_to_experimenter_name(cls)
953 if exp_name:
954 return "OF_EXPERIMENTER_ID_" + exp_name.upper()
955 return None
956
957def extension_to_subtype(cls, version):
958 """
959 Generic across all extension objects, return subtype identifier
960 """
961 for ext_obj in extension_objects:
962 for version, exp_list in ext_obj.items():
963 for exp_name, classes in exp_list.items():
964 if cls in classes:
965 return classes[cls]
966
967def class_is_extension(cls, version):
968 """
969 Return True if class, version is recognized as an extension
970 of any type (message, action....)
971
972 Accepts of_g.OF_VERSION_ANY
973 """
974
975 for ext_obj in extension_objects:
976 if cls_is_ext_obj(cls, version, ext_obj):
977 return True
978
979 return False
980
981# Internal
982def cls_is_ext_obj(cls, version, ext_obj):
983 """
984 @brief Return True if cls in an extension of type ext_obj
985 @param cls The class to check
986 @param version The version to check
987 @param ext_obj The extension object dictionary (messages, actions...)
988
989 Accepts of_g.VERSION_ANY
990 """
991
992 # Call with each version if "any" is passed
993 if version == of_g.VERSION_ANY:
994 for v in of_g.of_version_range:
995 if cls_is_ext_obj(cls, v, ext_obj):
996 return True
997 else: # Version specified
998 if version in ext_obj:
999 for exp, subtype_vals in ext_obj[version].items():
1000 if cls in subtype_vals:
1001 return True
1002
1003 return False
Andreas Wundsam53256162013-05-02 14:05:53 -07001004
Rich Lanea06d0c32013-03-25 08:52:03 -07001005################################################################
1006# These are extension message specific
1007################################################################
1008
1009def message_is_extension(cls, version):
1010 """
1011 Return True if cls, version is recognized as an extension
1012 This is brute force, searching records for a match
1013 """
1014 return cls_is_ext_obj(cls, version, extension_message_subtype)
1015
1016def extension_message_to_subtype(cls, version):
1017 """
1018 Return the subtype of the experimenter message if the class is an
1019 extension, else None
1020 """
1021 if version in extension_message_subtype:
1022 for exp, classes in extension_message_subtype[version].items():
1023 for ext_class, subtype in classes.items():
1024 if cls == ext_class:
1025 return subtype
1026 return None
1027
1028################################################################
1029# These are extension action specific
1030################################################################
1031
1032def action_is_extension(cls, version):
1033 """
1034 Return True if cls, version is recognized as an action extension
1035 This is brute force, searching records for a match
1036 """
1037 return cls_is_ext_obj(cls, version, extension_action_subtype)
1038
1039def extension_action_to_subtype(cls, version):
1040 """
1041 Return the ID of the action subtype (for its experimenteer)
1042 if class is an action extension, else None
1043 """
1044 if version in extension_action_subtype:
1045 for exp, classes in extension_action_subtype[version].items():
1046 if cls in classes:
1047 return classes[cls]
1048
1049 return None
1050
1051################################################################
1052# These are extension action specific
1053################################################################
1054
1055def action_id_is_extension(cls, version):
1056 """
1057 Return True if cls, version is recognized as an action ID extension
1058 This is brute force, searching records for a match
1059 """
1060 if version not in [of_g.VERSION_1_3]: # Action IDs only 1.3
1061 return False
1062 return cls_is_ext_obj(cls, version, extension_action_id_subtype)
1063
1064def extension_action_id_to_subtype(cls, version):
1065 """
1066 Return the ID of the action ID subtype (for its experimenteer)
1067 if class is an action ID extension, else None
1068 """
1069 if version in extension_action_id_subtype:
1070 for exp, classes in extension_action_id_subtype[version].items():
1071 if cls in classes:
1072 return classes[cls]
1073
1074 return None
1075
1076################################################################
1077# These are extension instruction specific
1078################################################################
1079
1080def instruction_is_extension(cls, version):
1081 """
1082 Return True if cls, version is recognized as an instruction extension
1083 This is brute force, searching records for a match
1084 """
1085 return cls_is_ext_obj(cls, version, extension_instruction_subtype)
1086
1087################################################################
1088# These are extension queue_prop specific
1089################################################################
1090
1091def queue_prop_is_extension(cls, version):
1092 """
1093 Return True if cls, version is recognized as an instruction extension
1094 This is brute force, searching records for a match
1095 """
1096 return cls_is_ext_obj(cls, version, extension_queue_prop_subtype)
1097
1098################################################################
1099# These are extension table_feature_prop specific
1100################################################################
1101
1102def table_feature_prop_is_extension(cls, version):
1103 """
1104 Return True if cls, version is recognized as an instruction extension
1105 This is brute force, searching records for a match
1106 """
1107 return cls_is_ext_obj(cls, version,
1108 extension_table_feature_prop_subtype)