blob: b16c07ccf3da4dd2e5e0923cb61c0f2be5393f32 [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
Rich Lanea06d0c32013-03-25 08:52:03 -0700396def class_is_virtual(cls):
397 """
398 Returns True if cls is a virtual class
399 """
400 if cls in inheritance_map:
401 return True
402 if cls.find("header") > 0:
403 return True
404 if loxi_utils.class_is_list(cls):
405 return True
406 return False
407
408################################################################
409#
410# These are message types
411#
412################################################################
413
414message_types = {
415 # version 1.0
416 of_g.VERSION_1_0:dict(
417 hello = 0,
418 error_msg = 1,
419 echo_request = 2,
420 echo_reply = 3,
421 experimenter = 4,
422 features_request = 5,
423 features_reply = 6,
424 get_config_request = 7,
425 get_config_reply = 8,
426 set_config = 9,
427 packet_in = 10,
428 flow_removed = 11,
429 port_status = 12,
430 packet_out = 13,
431 flow_mod = 14,
432 port_mod = 15,
433 stats_request = 16,
434 stats_reply = 17,
435 barrier_request = 18,
436 barrier_reply = 19,
437 queue_get_config_request = 20,
438 queue_get_config_reply = 21,
439 table_mod = 22 # Unofficial 1.0 extension
440 ),
441
442 # version 1.1
443 of_g.VERSION_1_1:dict(
444 hello = 0,
445 error_msg = 1,
446 echo_request = 2,
447 echo_reply = 3,
448 experimenter = 4,
449 features_request = 5,
450 features_reply = 6,
451 get_config_request = 7,
452 get_config_reply = 8,
453 set_config = 9,
454 packet_in = 10,
455 flow_removed = 11,
456 port_status = 12,
457 packet_out = 13,
458 flow_mod = 14,
459 group_mod = 15,
460 port_mod = 16,
461 table_mod = 17,
462 stats_request = 18,
463 stats_reply = 19,
464 barrier_request = 20,
465 barrier_reply = 21,
466 queue_get_config_request = 22,
467 queue_get_config_reply = 23
468 ),
469
470 # version 1.2
471 of_g.VERSION_1_2:dict(
472 hello = 0,
473 error_msg = 1,
474 echo_request = 2,
475 echo_reply = 3,
476 experimenter = 4,
477 features_request = 5,
478 features_reply = 6,
479 get_config_request = 7,
480 get_config_reply = 8,
481 set_config = 9,
482 packet_in = 10,
483 flow_removed = 11,
484 port_status = 12,
485 packet_out = 13,
486 flow_mod = 14,
487 group_mod = 15,
488 port_mod = 16,
489 table_mod = 17,
490 stats_request = 18,
491 stats_reply = 19,
492 barrier_request = 20,
493 barrier_reply = 21,
494 queue_get_config_request = 22,
495 queue_get_config_reply = 23,
496 role_request = 24,
497 role_reply = 25,
498 ),
499
500 # version 1.3
501 of_g.VERSION_1_3:dict(
502 hello = 0,
503 error_msg = 1,
504 echo_request = 2,
505 echo_reply = 3,
506 experimenter = 4,
507 features_request = 5,
508 features_reply = 6,
509 get_config_request = 7,
510 get_config_reply = 8,
511 set_config = 9,
512 packet_in = 10,
513 flow_removed = 11,
514 port_status = 12,
515 packet_out = 13,
516 flow_mod = 14,
517 group_mod = 15,
518 port_mod = 16,
519 table_mod = 17,
520 stats_request = 18, # FIXME Multipart
521 stats_reply = 19,
522 barrier_request = 20,
523 barrier_reply = 21,
524 queue_get_config_request = 22,
525 queue_get_config_reply = 23,
526 role_request = 24,
527 role_reply = 25,
528 async_get_request = 26,
529 async_get_reply = 27,
530 async_set = 28,
531 meter_mod = 29
532 )
533 }
534
535################################################################
536#
537# These are other objects that have a notion of type but are
538# not (yet) promoted to objects with inheritance
539#
540################################################################
541
542stats_types = {
543 # version 1.0
544 of_g.VERSION_1_0:dict(
545 desc = 0,
546 flow = 1,
547 aggregate = 2,
548 table = 3,
549 port = 4,
550 queue = 5,
551 experimenter = 0xffff
552 ),
553
554 # version 1.1
555 of_g.VERSION_1_1:dict(
556 desc = 0,
557 flow = 1,
558 aggregate = 2,
559 table = 3,
560 port = 4,
561 queue = 5,
562 group = 6,
563 group_desc = 7,
564 experimenter = 0xffff
565 ),
566
567 # version 1.2
568 of_g.VERSION_1_2:dict(
569 desc = 0,
570 flow = 1,
571 aggregate = 2,
572 table = 3,
573 port = 4,
574 queue = 5,
575 group = 6,
576 group_desc = 7,
577 group_features = 8,
578 experimenter = 0xffff
579 ),
580
581 # version 1.3
582 of_g.VERSION_1_3:dict(
583 desc = 0,
584 flow = 1,
585 aggregate = 2,
586 table = 3,
587 port = 4,
588 queue = 5,
589 group = 6,
590 group_desc = 7,
591 group_features = 8,
592 meter = 9,
593 meter_config = 10,
594 meter_features = 11,
595 table_features = 12,
596 port_desc = 13,
597 experimenter = 0xffff
598 )
599 }
600
601common_flow_mod_types = dict(
602 add = 0,
603 modify = 1,
604 modify_strict = 2,
605 delete = 3,
606 delete_strict = 4
607 )
608
609flow_mod_types = {
610 # version 1.0
611 of_g.VERSION_1_0:common_flow_mod_types,
612 of_g.VERSION_1_1:common_flow_mod_types,
613 of_g.VERSION_1_2:common_flow_mod_types,
614 of_g.VERSION_1_3:common_flow_mod_types
615 }
616
617# These do not translate to objects (yet)
618error_types = {
619 # version 1.0
620 of_g.VERSION_1_0:dict(
621 hello_failed = 0,
622 bad_request = 1,
623 bad_action = 2,
624 flow_mod_failed = 3,
625 port_mod_failed = 4,
626 queue_op_failed = 5
627 ),
628
629 # version 1.1
630 of_g.VERSION_1_1:dict(
631 hello_failed = 0,
632 bad_request = 1,
633 bad_action = 2,
634 bad_instruction = 3,
635 bad_match = 4,
636 flow_mod_failed = 5,
637 group_mod_failed = 6,
638 port_mod_failed = 7,
639 table_mod_failed = 8,
640 queue_op_failed = 9,
641 switch_config_failed = 10
642 ),
643
644 # version 1.2
645 of_g.VERSION_1_2:dict(
646 hello_failed = 0,
647 bad_request = 1,
648 bad_action = 2,
649 bad_instruction = 3,
650 bad_match = 4,
651 flow_mod_failed = 5,
652 group_mod_failed = 6,
653 port_mod_failed = 7,
654 table_mod_failed = 8,
655 queue_op_failed = 9,
656 switch_config_failed = 10,
657 role_request_failed = 11,
658 experimenter = 0xffff
659 ),
660
661 # version 1.3
662 of_g.VERSION_1_3:dict(
663 hello_failed = 0,
664 bad_request = 1,
665 bad_action = 2,
666 bad_instruction = 3,
667 bad_match = 4,
668 flow_mod_failed = 5,
669 group_mod_failed = 6,
670 port_mod_failed = 7,
671 table_mod_failed = 8,
672 queue_op_failed = 9,
673 switch_config_failed = 10,
674 role_request_failed = 11,
675 meter_mod_failed = 12,
676 table_features_failed= 13,
677 experimenter = 0xffff
678 )
679 }
680
681##
682# These are the objects whose length is specified by an external
683# reference, specifically another data member in the class.
Andreas Wundsam53256162013-05-02 14:05:53 -0700684#
Rich Lanea06d0c32013-03-25 08:52:03 -0700685#external_length_spec = {
686# ("of_packet_out", "actions", OF_VERSION_1_0) : "actions_len",
687# ("of_packet_out", "actions", OF_VERSION_1_1) : "actions_len",
688# ("of_packet_out", "actions", OF_VERSION_1_2) : "actions_len",
689# ("of_packet_out", "actions", OF_VERSION_1_3) : "actions_len"
690#}
691
692
693################################################################
694#
Andreas Wundsam53256162013-05-02 14:05:53 -0700695# type_val is the primary data structure that maps an
Rich Lanea06d0c32013-03-25 08:52:03 -0700696# (class_name, version) pair to the wire data type value
697#
698################################################################
699
700type_val = dict()
Rich Lane6bb28dd2013-05-13 15:19:14 -0700701inheritance_map = dict()
Rich Lanea06d0c32013-03-25 08:52:03 -0700702
Rich Lane6bb28dd2013-05-13 15:19:14 -0700703def generate_maps():
704 for parent, versioned in inheritance_data.items():
705 inheritance_map[parent] = set()
706 for ver, subclasses in versioned.items():
707 for subcls in subclasses:
708 inheritance_map[parent].add(subcls)
Rich Lanea06d0c32013-03-25 08:52:03 -0700709
Rich Lane6bb28dd2013-05-13 15:19:14 -0700710 for version, classes in message_types.items():
711 for cls in classes:
712 name = "of_" + cls
713 type_val[(name, version)] = classes[cls]
Rich Lanea06d0c32013-03-25 08:52:03 -0700714
Rich Lane6bb28dd2013-05-13 15:19:14 -0700715 for parent, versioned in inheritance_data.items():
716 for version, subclasses in versioned.items():
717 for subcls, value in subclasses.items():
718 name = parent + "_" + subcls
719 type_val[(name, version)] = value
720
721 # Special case OF-1.2 match type
722 type_val[("of_match_v3", of_g.VERSION_1_2)] = 0x8000
723 type_val[("of_match_v3", of_g.VERSION_1_3)] = 0x8000
Rich Lanea06d0c32013-03-25 08:52:03 -0700724
725# Utility function
726def dict_to_array(d, m_val, def_val=-1):
727 """
728 Given a dictionary, d, with each value a small integer,
729 produce an array indexed by the integer whose value is the key.
730 @param d The dictionary
731 @param m_val Ignore values greater than m_val
732 @param def_val The default value (for indices not in range of d)
733 """
734
735 # Get the max value in range for hash
736 max_val = 0
737 for key in d:
738 if (d[key] > max_val) and (d[key] < m_val):
739 max_val = d[key]
740 ar = []
741 for x in range(0, max_val + 1):
742 ar.append(def_val)
743 for key in d:
744 if (d[key] < m_val):
745 ar[d[key]] = key
746 return ar
747
748def type_array_len(version_indexed, max_val):
749 """
750 Given versioned information about a type, calculate how long
751 the unified array should be.
752
Andreas Wundsam53256162013-05-02 14:05:53 -0700753 @param version_indexed A dict indexed by version. Each value is a
Rich Lanea06d0c32013-03-25 08:52:03 -0700754 dict indexed by a name and whose value is an integer
755 @param max_val Ignore values greater than this for length calcs
756 """
757 # First, find the max length of all arrays
758 arr_len = 0
759 for version, val_dict in version_indexed.items():
760 ar = dict_to_array(val_dict, max_val, invalid_type)
761 if arr_len < len(ar):
762 arr_len = len(ar)
763 return arr_len
764
765# FIXME: Need to move update for multipart messages
766
767stats_reply_list = [
768 "of_aggregate_stats_reply",
769 "of_desc_stats_reply",
770 "of_experimenter_stats_reply",
771 "of_flow_stats_reply",
772 "of_group_stats_reply",
773 "of_group_desc_stats_reply",
774 "of_group_features_stats_reply",
775 "of_meter_stats_reply",
776 "of_meter_config_stats_reply",
777 "of_meter_features_stats_reply",
778 "of_port_stats_reply",
779 "of_port_desc_stats_reply",
780 "of_queue_stats_reply",
781 "of_table_stats_reply",
782 "of_table_features_stats_reply"
783]
784
785stats_request_list = [
786 "of_aggregate_stats_request",
787 "of_desc_stats_request",
788 "of_experimenter_stats_request",
789 "of_flow_stats_request",
790 "of_group_stats_request",
791 "of_group_desc_stats_request",
792 "of_group_features_stats_request",
793 "of_meter_stats_request",
794 "of_meter_config_stats_request",
795 "of_meter_features_stats_request",
796 "of_port_stats_request",
797 "of_port_desc_stats_request",
798 "of_queue_stats_request",
799 "of_table_stats_request",
800 "of_table_features_stats_request"
801]
802
803flow_mod_list = [
804 "of_flow_add",
805 "of_flow_modify",
806 "of_flow_modify_strict",
807 "of_flow_delete",
808 "of_flow_delete_strict"
809]
810
811def sub_class_map(base_type, version):
812 """
813 Returns an iterable object giving the instance nameys and subclass types
814 for the base_type, version values
815 """
816 rv = []
817 if base_type not in inheritance_map:
818 return rv
819
820 for instance in inheritance_map[base_type]:
821 subcls = loxi_utils.instance_to_class(instance, base_type)
822 if not loxi_utils.class_in_version(subcls, version):
823 continue
824 rv.append((instance, subcls))
825
826 return rv
827
828################################################################
829#
830# Extension related data and functions
831#
832################################################################
833
834# Per OF Version, per experimenter, map exp msg type (subtype) to object IDs
835# @fixme Generate defines for OF_<exp>_SUBTYPE_<msg> for the values below?
836extension_message_subtype = {
837 # version 1.0
838 of_g.VERSION_1_0:dict( # Version 1.0 extensions
839 bsn = { # BSN extensions; indexed by class name, value is subtype
840 "of_bsn_set_ip_mask" : 0,
841 "of_bsn_get_ip_mask_request" : 1,
842 "of_bsn_get_ip_mask_reply" : 2,
843 "of_bsn_set_mirroring" : 3,
844 "of_bsn_get_mirroring_request" : 4,
845 "of_bsn_get_mirroring_reply" : 5,
846 "of_bsn_shell_command" : 6,
847 "of_bsn_shell_output" : 7,
848 "of_bsn_shell_status" : 8,
849 "of_bsn_get_interfaces_request" : 9,
850 "of_bsn_get_interfaces_reply" : 10,
Rich Lanefd2fcd52013-03-28 09:18:31 -0700851 "of_bsn_set_pktin_suppression" : 11,
Ken Chiang103e1472013-05-13 17:21:57 -0700852 "of_bsn_set_l2_table" : 12,
853 "of_bsn_get_l2_table_request" : 13,
854 "of_bsn_get_l2_table_reply" : 14,
Rich Lanea06d0c32013-03-25 08:52:03 -0700855 },
856 nicira = { # Nicira extensions, value is subtype
857 "of_nicira_controller_role_request" : 10,
858 "of_nicira_controller_role_reply" : 11,
859 },
860 ),
861 of_g.VERSION_1_1:dict( # Version 1.0 extensions
862 bsn = { # BSN extensions; indexed by class name, value is subtype
863 "of_bsn_set_mirroring" : 3,
864 "of_bsn_get_mirroring_request" : 4,
865 "of_bsn_get_mirroring_reply" : 5,
866 "of_bsn_get_interfaces_request" : 9,
867 "of_bsn_get_interfaces_reply" : 10,
Rich Lanefd2fcd52013-03-28 09:18:31 -0700868 "of_bsn_set_pktin_suppression" : 11,
Rich Lanea06d0c32013-03-25 08:52:03 -0700869 },
870 ),
871 of_g.VERSION_1_2:dict( # Version 1.0 extensions
872 bsn = { # BSN extensions; indexed by class name, value is subtype
873 "of_bsn_set_mirroring" : 3,
874 "of_bsn_get_mirroring_request" : 4,
875 "of_bsn_get_mirroring_reply" : 5,
876 "of_bsn_get_interfaces_request" : 9,
877 "of_bsn_get_interfaces_reply" : 10,
Rich Lanefd2fcd52013-03-28 09:18:31 -0700878 "of_bsn_set_pktin_suppression" : 11,
Rich Lanea06d0c32013-03-25 08:52:03 -0700879 },
880 ),
881 of_g.VERSION_1_3:dict( # Version 1.0 extensions
882 bsn = { # BSN extensions; indexed by class name, value is subtype
883 "of_bsn_set_mirroring" : 3,
884 "of_bsn_get_mirroring_request" : 4,
885 "of_bsn_get_mirroring_reply" : 5,
886 "of_bsn_get_interfaces_request" : 9,
887 "of_bsn_get_interfaces_reply" : 10,
Rich Lanefd2fcd52013-03-28 09:18:31 -0700888 "of_bsn_set_pktin_suppression" : 11,
Rich Lanea06d0c32013-03-25 08:52:03 -0700889 },
890 ),
891}
892
893# Set to empty dict if no extension actions defined
894# Per OF Version, per experimenter, map actions to subtype
895extension_action_subtype = {
896 # version 1.0
897 of_g.VERSION_1_0:dict( # Version 1.0 extensions
898 bsn = { # of_action_bsn_
899 "of_action_bsn_mirror" : 1,
900 "of_action_bsn_set_tunnel_dst" : 2,
901 },
902 nicira = { # of_action_nicira_
903 "of_action_nicira_dec_ttl" : 18,
904 }
905 ),
906 of_g.VERSION_1_1:dict( # Version 1.0 extensions
907 bsn = { # of_action_bsn_
908 "of_action_bsn_mirror" : 1,
909 "of_action_bsn_set_tunnel_dst" : 2,
910 },
911 nicira = { # of_action_nicira_
912 "of_action_nicira_dec_ttl" : 18,
913 }
914 ),
915 of_g.VERSION_1_2:dict( # Version 1.0 extensions
916 bsn = { # of_action_bsn_
917 "of_action_bsn_mirror" : 1,
918 "of_action_bsn_set_tunnel_dst" : 2,
919 },
920 nicira = { # of_action_nicira_
921 "of_action_nicira_dec_ttl" : 18,
922 }
923 ),
924 of_g.VERSION_1_3:dict( # Version 1.0 extensions
925 bsn = { # of_action_bsn_
926 "of_action_bsn_mirror" : 1,
927 "of_action_bsn_set_tunnel_dst" : 2,
928 },
929 nicira = { # of_action_nicira_
930 "of_action_nicira_dec_ttl" : 18,
931 }
932 ),
933}
934
935# Set to empty dict if no extension actions defined
936# Per OF Version, per experimenter, map actions to subtype
937extension_action_id_subtype = {
938 # version 1.0
939 of_g.VERSION_1_0:dict(),
940 of_g.VERSION_1_1:dict(),
941 of_g.VERSION_1_2:dict(),
942 of_g.VERSION_1_3:dict( # Version 1.3 extensions
943 bsn = { # of_action_bsn_
944 "of_action_id_bsn_mirror" : 1,
945 "of_action_id_bsn_set_tunnel_dst" : 2,
946 },
947 nicira = { # of_action_nicira_
948 "of_action_id_nicira_dec_ttl" : 18,
949 }
950 ),
951}
952
953# Set to empty dict if no extension instructions defined
954extension_instruction_subtype = {}
955
956# Set to empty dict if no extension instructions defined
957extension_queue_prop_subtype = {}
958
959# Set to empty dict if no extension instructions defined
960extension_table_feature_prop_subtype = {}
961
962extension_objects = [
963 extension_message_subtype,
964 extension_action_subtype,
965 extension_action_id_subtype,
966 extension_instruction_subtype,
967 extension_queue_prop_subtype,
968 extension_table_feature_prop_subtype
969]
970
971################################################################
972# These are extension type generic (for messages, actions...)
973################################################################
974
975def extension_to_experimenter_name(cls):
976 """
977 Return the name of the experimenter if class is an
978 extension, else None
979
980 This is brute force; we search all extension data for a match
981 """
Andreas Wundsam53256162013-05-02 14:05:53 -0700982
Rich Lanea06d0c32013-03-25 08:52:03 -0700983 for ext_obj in extension_objects:
984 for version, exp_list in ext_obj.items():
985 for exp_name, classes in exp_list.items():
986 if cls in classes:
987 return exp_name
988 return None
989
990def extension_to_experimenter_id(cls):
991 """
992 Return the ID of the experimenter if class is an
993 extension, else None
994 """
995 exp_name = extension_to_experimenter_name(cls)
996 if exp_name:
997 return of_g.experimenter_name_to_id[exp_name]
998 return None
999
1000def extension_to_experimenter_macro_name(cls):
1001 """
1002 Return the "macro name" of the ID of the experimenter if class is an
1003 extension, else None
1004 """
1005 exp_name = extension_to_experimenter_name(cls)
1006 if exp_name:
1007 return "OF_EXPERIMENTER_ID_" + exp_name.upper()
1008 return None
1009
1010def extension_to_subtype(cls, version):
1011 """
1012 Generic across all extension objects, return subtype identifier
1013 """
1014 for ext_obj in extension_objects:
1015 for version, exp_list in ext_obj.items():
1016 for exp_name, classes in exp_list.items():
1017 if cls in classes:
1018 return classes[cls]
1019
1020def class_is_extension(cls, version):
1021 """
1022 Return True if class, version is recognized as an extension
1023 of any type (message, action....)
1024
1025 Accepts of_g.OF_VERSION_ANY
1026 """
1027
1028 for ext_obj in extension_objects:
1029 if cls_is_ext_obj(cls, version, ext_obj):
1030 return True
1031
1032 return False
1033
1034# Internal
1035def cls_is_ext_obj(cls, version, ext_obj):
1036 """
1037 @brief Return True if cls in an extension of type ext_obj
1038 @param cls The class to check
1039 @param version The version to check
1040 @param ext_obj The extension object dictionary (messages, actions...)
1041
1042 Accepts of_g.VERSION_ANY
1043 """
1044
1045 # Call with each version if "any" is passed
1046 if version == of_g.VERSION_ANY:
1047 for v in of_g.of_version_range:
1048 if cls_is_ext_obj(cls, v, ext_obj):
1049 return True
1050 else: # Version specified
1051 if version in ext_obj:
1052 for exp, subtype_vals in ext_obj[version].items():
1053 if cls in subtype_vals:
1054 return True
1055
1056 return False
Andreas Wundsam53256162013-05-02 14:05:53 -07001057
Rich Lanea06d0c32013-03-25 08:52:03 -07001058################################################################
1059# These are extension message specific
1060################################################################
1061
1062def message_is_extension(cls, version):
1063 """
1064 Return True if cls, version is recognized as an extension
1065 This is brute force, searching records for a match
1066 """
1067 return cls_is_ext_obj(cls, version, extension_message_subtype)
1068
1069def extension_message_to_subtype(cls, version):
1070 """
1071 Return the subtype of the experimenter message if the class is an
1072 extension, else None
1073 """
1074 if version in extension_message_subtype:
1075 for exp, classes in extension_message_subtype[version].items():
1076 for ext_class, subtype in classes.items():
1077 if cls == ext_class:
1078 return subtype
1079 return None
1080
1081################################################################
1082# These are extension action specific
1083################################################################
1084
1085def action_is_extension(cls, version):
1086 """
1087 Return True if cls, version is recognized as an action extension
1088 This is brute force, searching records for a match
1089 """
1090 return cls_is_ext_obj(cls, version, extension_action_subtype)
1091
1092def extension_action_to_subtype(cls, version):
1093 """
1094 Return the ID of the action subtype (for its experimenteer)
1095 if class is an action extension, else None
1096 """
1097 if version in extension_action_subtype:
1098 for exp, classes in extension_action_subtype[version].items():
1099 if cls in classes:
1100 return classes[cls]
1101
1102 return None
1103
1104################################################################
1105# These are extension action specific
1106################################################################
1107
1108def action_id_is_extension(cls, version):
1109 """
1110 Return True if cls, version is recognized as an action ID extension
1111 This is brute force, searching records for a match
1112 """
1113 if version not in [of_g.VERSION_1_3]: # Action IDs only 1.3
1114 return False
1115 return cls_is_ext_obj(cls, version, extension_action_id_subtype)
1116
1117def extension_action_id_to_subtype(cls, version):
1118 """
1119 Return the ID of the action ID subtype (for its experimenteer)
1120 if class is an action ID extension, else None
1121 """
1122 if version in extension_action_id_subtype:
1123 for exp, classes in extension_action_id_subtype[version].items():
1124 if cls in classes:
1125 return classes[cls]
1126
1127 return None
1128
1129################################################################
1130# These are extension instruction specific
1131################################################################
1132
1133def instruction_is_extension(cls, version):
1134 """
1135 Return True if cls, version is recognized as an instruction extension
1136 This is brute force, searching records for a match
1137 """
1138 return cls_is_ext_obj(cls, version, extension_instruction_subtype)
1139
1140################################################################
1141# These are extension queue_prop specific
1142################################################################
1143
1144def queue_prop_is_extension(cls, version):
1145 """
1146 Return True if cls, version is recognized as an instruction extension
1147 This is brute force, searching records for a match
1148 """
1149 return cls_is_ext_obj(cls, version, extension_queue_prop_subtype)
1150
1151################################################################
1152# These are extension table_feature_prop specific
1153################################################################
1154
1155def table_feature_prop_is_extension(cls, version):
1156 """
1157 Return True if cls, version is recognized as an instruction extension
1158 This is brute force, searching records for a match
1159 """
1160 return cls_is_ext_obj(cls, version,
1161 extension_table_feature_prop_subtype)