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