blob: a7da7514ad584dc0955caaac88644099754919e9 [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# @brief Match data representation
29#
30# @fixme This still has lots of C specific code that should be moved into c_gen
31
32import sys
Andreas Wundsam542a13c2013-11-15 13:28:55 -080033import c_gen.of_g_legacy as of_g
Rich Lanea06d0c32013-03-25 08:52:03 -070034from generic_utils import *
Andreas Wundsam542a13c2013-11-15 13:28:55 -080035import c_gen.loxi_utils_legacy as loxi_utils
Rich Lanea06d0c32013-03-25 08:52:03 -070036
37#
38# Use 1.2 match semantics for common case
39#
40# Generate maps between generic match and version specific matches
41# Generate dump functions for generic match
42# Generate dump functions for version specific matches
43
44## @var of_match_members
45# The dictionary from unified match members to type and indexing info
46#
47# Keys:
48# name The unified name used for the member
49# m_type The data type used for the object in unified structure
50# print_type The id to use when printing
51# conditions The condition underwhich the field could occur TBD
52# takes_mask_in_spec Shown as taking mask in OF 1.2 spec; IGNORED NOW
53# order Used to define an order for readability
54# v1_wc_shift The WC shift in OF 1.0
55# v2_wc_shift The WC shift in OF 1.1
56#
57# Unless noted otherwise, class is 0x8000, OFPXMC_OPENFLOW_BASIC
58# We use the 1.2 names and alias older names
59# Conditions:
60# is_ipv4(_m): ((_m)->eth_type == 0x0800)
61# is_ipv6(_m): ((_m)->eth_type == 0x86dd)
62# is_ip(_m): (is_ipv4(_m) || is_ipv6(_m))
63# is_arp(_m): ((_m)->eth_type == 0x0806)
64# is_tcp(_m): (is_ip(_m) && ((_m)->ip_proto == 6))
65# is_udp(_m): (is_ip(_m) && ((_m)->ip_proto == 17))
66# is_sctp(_m): (is_ip(_m) && ((_m)->ip_proto == 132))
67# is_icmpv4(_m): (is_ipv4(_m) && ((_m)->ip_proto == 1))
68# is_icmpv6(_m): (is_ipv6(_m) && ((_m)->ip_proto == 58))
69#
70
71of_match_members = dict(
72 in_port = dict(
73 name="in_port",
74 m_type="of_port_no_t",
75 print_type="PRIx32",
76 conditions="",
77 v1_wc_shift=0,
78 v2_wc_shift=0,
79 takes_mask_in_spec=False,
80 order=100,
81 ),
82 in_phy_port = dict(
83 name="in_phy_port",
84 m_type="of_port_no_t",
85 print_type="PRIx32",
86 conditions="", # OXM_OF_IN_PORT must be present
87 takes_mask_in_spec=False,
88 order=101,
89 ),
90 metadata = dict(
91 name="metadata",
92 m_type="uint64_t",
93 print_type="PRIx64",
94 conditions="",
95 takes_mask_in_spec=True,
96 order=102,
97 ),
98
99 eth_dst = dict(
100 name="eth_dst",
101 m_type="of_mac_addr_t",
102 v1_wc_shift=3,
103 print_type="\"p\"",
104 conditions="",
105 takes_mask_in_spec=True,
106 order=200,
107 ),
108 eth_src = dict(
109 name="eth_src",
110 m_type="of_mac_addr_t",
111 v1_wc_shift=2,
112 print_type="\"p\"",
113 conditions="",
114 takes_mask_in_spec=True,
115 order=201,
116 ),
117 eth_type = dict(
118 name="eth_type",
119 m_type="uint16_t",
120 v1_wc_shift=4,
121 v2_wc_shift=3,
122 print_type="PRIx16",
123 conditions="",
124 takes_mask_in_spec=False,
125 order=203,
126 ),
127 vlan_vid = dict( # FIXME: Semantics changed in 1.2
128 # Use CFI bit to indicate tag presence
129 name="vlan_vid",
130 m_type="uint16_t",
131 v1_wc_shift=1,
132 v2_wc_shift=1,
133 print_type="PRIx16",
134 conditions="",
135 takes_mask_in_spec=True,
136 order=210,
137 ),
138 vlan_pcp = dict(
139 name="vlan_pcp",
140 m_type="uint8_t",
141 v1_wc_shift=20,
142 v2_wc_shift=2,
143 print_type="PRIx8",
144 conditions="",
145 takes_mask_in_spec=False,
146 order=211,
147 ),
Rich Lane4964d542013-10-14 18:13:47 -0700148
Rich Lanea06d0c32013-03-25 08:52:03 -0700149 ip_dscp = dict(
150 name="ip_dscp",
151 m_type="uint8_t",
152 v1_wc_shift=21,
153 v2_wc_shift=4,
154 print_type="PRIx8",
155 conditions="is_ip(match)",
156 takes_mask_in_spec=False,
157 order=310,
158 ),
159 ip_ecn = dict(
160 name="ip_ecn",
161 m_type="uint8_t",
162 print_type="PRIx8",
163 conditions="is_ip(match)",
164 takes_mask_in_spec=False,
165 order=311,
166 ),
167 ip_proto = dict(
168 name="ip_proto",
169 m_type="uint8_t",
170 v1_wc_shift=5,
171 v2_wc_shift=5,
172 print_type="PRIx8",
173 conditions="is_ip(match)",
174 takes_mask_in_spec=False,
175 order=320,
176 ),
Rich Lane4964d542013-10-14 18:13:47 -0700177 ipv4_src = dict(
178 name="ipv4_src",
179 m_type="of_ipv4_t",
180 v1_wc_shift=8,
181 print_type="PRIx32",
182 conditions="is_ipv4(match)",
183 takes_mask_in_spec=True,
184 order=330,
185 ),
186 ipv4_dst = dict(
187 name="ipv4_dst",
188 m_type="of_ipv4_t",
189 v1_wc_shift=14,
190 print_type="PRIx32",
191 conditions="is_ipv4(match)",
192 takes_mask_in_spec=True,
193 order=331,
194 ),
Rich Lanea06d0c32013-03-25 08:52:03 -0700195
196 tcp_dst = dict(
197 name="tcp_dst",
198 m_type="uint16_t",
199 v1_wc_shift=7,
200 v2_wc_shift=7,
201 print_type="PRIx16",
202 conditions="is_tcp(match)",
203 takes_mask_in_spec=False,
204 order=400,
205 ),
206 tcp_src = dict(
207 name="tcp_src",
208 m_type="uint16_t",
209 v1_wc_shift=6,
210 v2_wc_shift=6,
211 print_type="PRIx16",
212 conditions="is_tcp(match)",
213 takes_mask_in_spec=False,
214 order=401,
215 ),
216
217 udp_dst = dict(
218 name="udp_dst",
219 m_type="uint16_t",
220 print_type="PRIx16",
221 conditions="is_udp(match)",
222 takes_mask_in_spec=False,
223 order=410,
224 ),
225 udp_src = dict(
226 name="udp_src",
227 m_type="uint16_t",
228 print_type="PRIx16",
229 conditions="is_udp(match)",
230 takes_mask_in_spec=False,
231 order=411,
232 ),
233
234 sctp_dst = dict(
235 name="sctp_dst",
236 m_type="uint16_t",
237 print_type="PRIx16",
238 conditions="is_sctp(match)",
239 takes_mask_in_spec=False,
240 order=420,
241 ),
242 sctp_src = dict(
243 name="sctp_src",
244 m_type="uint16_t",
245 print_type="PRIx16",
246 conditions="is_sctp(match)",
247 takes_mask_in_spec=False,
248 order=421,
249 ),
250
251 icmpv4_type = dict(
252 name="icmpv4_type",
253 m_type="uint8_t",
254 print_type="PRIx8",
255 conditions="is_icmp_v4(match)",
256 takes_mask_in_spec=False,
257 order=430,
258 ),
259 icmpv4_code = dict(
260 name="icmpv4_code",
261 m_type="uint8_t",
262 print_type="PRIx8",
263 conditions="is_icmp_v4(match)",
264 takes_mask_in_spec=False,
265 order=431,
266 ),
267
268 arp_op = dict(
269 name="arp_op",
270 m_type="uint16_t",
271 print_type="PRIx16",
272 conditions="is_arp(match)",
273 takes_mask_in_spec=False,
Rich Lane4964d542013-10-14 18:13:47 -0700274 order=450,
Rich Lanea06d0c32013-03-25 08:52:03 -0700275 ),
276
277 arp_spa = dict(
278 name="arp_spa",
279 m_type="uint32_t",
280 print_type="PRIx32",
281 conditions="is_arp(match)",
282 takes_mask_in_spec=True,
Rich Lane4964d542013-10-14 18:13:47 -0700283 order=451,
Rich Lanea06d0c32013-03-25 08:52:03 -0700284 ),
285 arp_tpa = dict(
286 name="arp_tpa",
287 m_type="uint32_t",
288 print_type="PRIx32",
289 conditions="is_arp(match)",
290 takes_mask_in_spec=True,
Rich Lane4964d542013-10-14 18:13:47 -0700291 order=452,
Rich Lanea06d0c32013-03-25 08:52:03 -0700292 ),
293
294 arp_sha = dict(
295 name="arp_sha",
296 m_type="of_mac_addr_t",
297 print_type="\"p\"",
298 conditions="is_arp(match)",
299 takes_mask_in_spec=False,
Rich Lane4964d542013-10-14 18:13:47 -0700300 order=453,
Rich Lanea06d0c32013-03-25 08:52:03 -0700301 ),
302 arp_tha = dict(
303 name="arp_tha",
304 m_type="of_mac_addr_t",
305 print_type="\"p\"",
306 conditions="is_arp(match)",
307 takes_mask_in_spec=False,
Rich Lane4964d542013-10-14 18:13:47 -0700308 order=454,
Rich Lanea06d0c32013-03-25 08:52:03 -0700309 ),
310
311 ipv6_src = dict(
312 name="ipv6_src",
313 m_type="of_ipv6_t",
314 print_type="\"p\"",
315 conditions="is_ipv6(match)",
316 takes_mask_in_spec=True,
Rich Lane4964d542013-10-14 18:13:47 -0700317 order=500,
Rich Lanea06d0c32013-03-25 08:52:03 -0700318 ),
319 ipv6_dst = dict(
320 name="ipv6_dst",
321 m_type="of_ipv6_t",
322 print_type="\"p\"",
323 conditions="is_ipv6(match)",
324 takes_mask_in_spec=True,
Rich Lane4964d542013-10-14 18:13:47 -0700325 order=501,
Rich Lanea06d0c32013-03-25 08:52:03 -0700326 ),
327
328 ipv6_flabel = dict(
329 name="ipv6_flabel",
330 m_type="uint32_t",
331 print_type="PRIx32",
332 conditions="is_ipv6(match)",
333 takes_mask_in_spec=False, # Comment in openflow.h says True
Rich Lane4964d542013-10-14 18:13:47 -0700334 order=502,
Rich Lanea06d0c32013-03-25 08:52:03 -0700335 ),
336
337 icmpv6_type = dict(
338 name="icmpv6_type",
339 m_type="uint8_t",
340 print_type="PRIx8",
341 conditions="is_icmp_v6(match)",
342 takes_mask_in_spec=False,
Rich Lane4964d542013-10-14 18:13:47 -0700343 order=510,
Rich Lanea06d0c32013-03-25 08:52:03 -0700344 ),
345 icmpv6_code = dict(
346 name="icmpv6_code",
347 m_type="uint8_t",
348 print_type="PRIx8",
349 conditions="is_icmp_v6(match)",
350 takes_mask_in_spec=False,
Rich Lane4964d542013-10-14 18:13:47 -0700351 order=511,
Rich Lanea06d0c32013-03-25 08:52:03 -0700352 ),
353
354 ipv6_nd_target = dict(
355 name="ipv6_nd_target",
356 m_type="of_ipv6_t",
357 print_type="\"p\"",
358 conditions="", # fixme
359 takes_mask_in_spec=False,
Rich Lane4964d542013-10-14 18:13:47 -0700360 order=512,
Rich Lanea06d0c32013-03-25 08:52:03 -0700361 ),
362
363 ipv6_nd_sll = dict(
364 name="ipv6_nd_sll",
365 m_type="of_mac_addr_t",
366 print_type="\"p\"",
367 conditions="", # fixme
368 takes_mask_in_spec=False,
Rich Lane4964d542013-10-14 18:13:47 -0700369 order=520,
Rich Lanea06d0c32013-03-25 08:52:03 -0700370 ),
371 ipv6_nd_tll = dict(
372 name="ipv6_nd_tll",
373 m_type="of_mac_addr_t",
374 print_type="\"p\"",
375 conditions="", # fixme
376 takes_mask_in_spec=False,
Rich Lane4964d542013-10-14 18:13:47 -0700377 order=521,
Rich Lanea06d0c32013-03-25 08:52:03 -0700378 ),
379
380 mpls_label = dict(
381 name="mpls_label",
382 m_type="uint32_t",
383 v2_wc_shift=8,
384 print_type="PRIx32",
385 conditions="",
386 takes_mask_in_spec=False,
Rich Lane4964d542013-10-14 18:13:47 -0700387 order=600,
Rich Lanea06d0c32013-03-25 08:52:03 -0700388 ),
389 mpls_tc = dict(
390 name="mpls_tc",
391 m_type="uint8_t",
392 v2_wc_shift=9,
393 print_type="PRIx8",
394 conditions="",
395 takes_mask_in_spec=False,
Rich Lane4964d542013-10-14 18:13:47 -0700396 order=601,
Rich Lanea06d0c32013-03-25 08:52:03 -0700397 ),
Rich Laned8d29c92013-09-24 13:46:42 -0700398
399 bsn_in_ports_128 = dict(
400 name="bsn_in_ports_128",
401 m_type="of_bitmap_128_t",
402 v2_wc_shift=9,
403 print_type="p",
404 conditions="",
405 takes_mask_in_spec=True,
406 order=1000,
407 ),
Rich Lane61718362013-10-24 16:59:42 -0700408
409 bsn_lag_id = dict(
410 name="bsn_lag_id",
411 m_type="uint32_t",
412 print_type="PRIu32",
413 conditions="",
414 takes_mask_in_spec=False,
415 order=1001,
416 ),
Rich Laneeb21c4f2013-10-28 17:34:41 -0700417
418 bsn_vrf = dict(
419 name="bsn_vrf",
420 m_type="uint32_t",
421 print_type="PRIu32",
422 conditions="",
423 takes_mask_in_spec=False,
424 order=1002,
425 ),
426
427 bsn_global_vrf_allowed = dict(
428 name="bsn_global_vrf_allowed",
429 m_type="uint8_t",
430 print_type="PRIu8",
431 conditions="",
432 takes_mask_in_spec=False,
433 order=1003,
434 ),
435
436 bsn_l3_interface_class_id = dict(
437 name="bsn_l3_interface_class_id",
438 m_type="uint32_t",
439 print_type="PRIu32",
440 conditions="",
441 takes_mask_in_spec=True,
442 order=1003,
443 ),
444
445 bsn_l3_src_class_id = dict(
446 name="bsn_l3_src_class_id",
447 m_type="uint32_t",
448 print_type="PRIu32",
449 conditions="",
450 takes_mask_in_spec=True,
451 order=1004,
452 ),
453
454 bsn_l3_dst_class_id = dict(
455 name="bsn_l3_dst_class_id",
456 m_type="uint32_t",
457 print_type="PRIu32",
458 conditions="",
459 takes_mask_in_spec=True,
460 order=1005,
461 ),
Rich Laneadb94812014-03-11 17:13:07 -0700462
463 bsn_egr_port_group_id = dict(
464 name="bsn_egr_port_group_id",
465 m_type="uint32_t",
466 print_type="PRIu32",
467 conditions="",
468 takes_mask_in_spec=True,
469 order=1006,
470 ),
Rich Lane53ddf5c2014-03-20 15:24:08 -0700471
472 bsn_udf0 = dict(
473 name="bsn_udf0",
474 m_type="uint32_t",
475 print_type="PRIu32",
476 conditions="",
477 takes_mask_in_spec=True,
478 order=1010,
479 ),
480
481 bsn_udf1 = dict(
482 name="bsn_udf1",
483 m_type="uint32_t",
484 print_type="PRIu32",
485 conditions="",
486 takes_mask_in_spec=True,
487 order=1010,
488 ),
489
490 bsn_udf2 = dict(
491 name="bsn_udf2",
492 m_type="uint32_t",
493 print_type="PRIu32",
494 conditions="",
495 takes_mask_in_spec=True,
496 order=1010,
497 ),
498
499 bsn_udf3 = dict(
500 name="bsn_udf3",
501 m_type="uint32_t",
502 print_type="PRIu32",
503 conditions="",
504 takes_mask_in_spec=True,
505 order=1010,
506 ),
507
508 bsn_udf4 = dict(
509 name="bsn_udf4",
510 m_type="uint32_t",
511 print_type="PRIu32",
512 conditions="",
513 takes_mask_in_spec=True,
514 order=1010,
515 ),
516
517 bsn_udf5 = dict(
518 name="bsn_udf5",
519 m_type="uint32_t",
520 print_type="PRIu32",
521 conditions="",
522 takes_mask_in_spec=True,
523 order=1010,
524 ),
525
526 bsn_udf6 = dict(
527 name="bsn_udf6",
528 m_type="uint32_t",
529 print_type="PRIu32",
530 conditions="",
531 takes_mask_in_spec=True,
532 order=1010,
533 ),
534
535 bsn_udf7 = dict(
536 name="bsn_udf7",
537 m_type="uint32_t",
538 print_type="PRIu32",
539 conditions="",
540 takes_mask_in_spec=True,
541 order=1010,
542 ),
Rich Lane9b178072014-05-19 15:31:55 -0700543
544 bsn_tcp_flags = dict(
545 name="bsn_tcp_flags",
546 m_type="uint16_t",
547 print_type="PRIx16",
548 conditions="",
549 takes_mask_in_spec=True,
550 order=1010,
551 ),
Rich Lanea06d0c32013-03-25 08:52:03 -0700552)
553
554match_keys_sorted = of_match_members.keys()
555match_keys_sorted.sort(key=lambda entry:of_match_members[entry]["order"])
556
557of_v1_keys = [
558 "eth_dst",
559 "eth_src",
560 "eth_type",
561 "in_port",
562 "ipv4_dst",
563 "ip_proto",
564 "ipv4_src",
565 "ip_dscp",
566 "tcp_dst", # Means UDP too for 1.0 and 1.1
567 "tcp_src", # Means UDP too for 1.0 and 1.1
568 "vlan_pcp",
Rob Sherwood53989c82013-07-03 16:49:50 -0700569 "vlan_vid"
Rich Lanea06d0c32013-03-25 08:52:03 -0700570 ]
571
572of_v2_keys = [
573 "eth_dst",
574 "eth_src",
575 "eth_type",
576 "in_port",
577 "ipv4_dst",
578 "ip_proto",
579 "ipv4_src",
580 "ip_dscp",
581 "tcp_dst", # Means UDP too for 1.0 and 1.1
582 "tcp_src", # Means UDP too for 1.0 and 1.1
583 "vlan_pcp",
584 "vlan_vid",
585 "mpls_label",
586 "mpls_tc",
587 "metadata"
588 ]
589
590of_v2_full_mask = [
591 "eth_dst",
592 "eth_src",
593 "ipv4_dst",
594 "ipv4_src",
595 "metadata"
596 ]
597
Rich Lanea06d0c32013-03-25 08:52:03 -0700598##
599# Check that all members in the hash are recognized as match keys
600def match_sanity_check():
601 count = 0
602 for match_v in ["of_match_v1", "of_match_v2"]:
603 count += 1
604 for mm in of_g.unified[match_v][count]["members"]:
605 key = mm["name"]
606 if key.find("_mask") >= 0:
607 continue
608 if loxi_utils.skip_member_name(key):
609 continue
610 if key == "wildcards":
611 continue
612 if not key in of_match_members:
613 print "Key %s not found in match struct, v %s" % (key, match_v)
614 sys.exit(1)
615
Rich Lane883919c2013-05-09 17:53:18 -0700616 # Generate list of OXM names from the unified classes
617 oxm_names = [x[7:] for x in of_g.unified.keys() if
618 x.startswith('of_oxm_') and
619 x.find('masked') < 0 and
620 x.find('header') < 0]
621
622 # Check that all OXMs are in the match members
623 for key in oxm_names:
Rich Lanea06d0c32013-03-25 08:52:03 -0700624 if not key in of_match_members:
625 if not (key.find("_masked") > 0):
Rich Lane883919c2013-05-09 17:53:18 -0700626 debug("Key %s in OXM, not of_match_members" % key)
Rich Lanea06d0c32013-03-25 08:52:03 -0700627 sys.exit(1)
628 if not key[:-7] in of_match_members:
Rich Lane883919c2013-05-09 17:53:18 -0700629 debug("Key %s in OXM, but %s not in of_match_members"
Rich Lanea06d0c32013-03-25 08:52:03 -0700630 % (key, key[:-7]))
631 sys.exit(1)
632
Rich Lane883919c2013-05-09 17:53:18 -0700633 # Check that all match members are in the OXMs
Rich Lanea06d0c32013-03-25 08:52:03 -0700634 for key in of_match_members:
Rich Lane883919c2013-05-09 17:53:18 -0700635 if not key in oxm_names:
636 debug("Key %s in of_match_members, not in OXM" % key)
Rich Lanea06d0c32013-03-25 08:52:03 -0700637 sys.exit(1)
Rich Lane883919c2013-05-09 17:53:18 -0700638 oxm_type = of_g.unified['of_oxm_%s' % key]['union']['value']['m_type']
639 if of_match_members[key]["m_type"] != oxm_type:
Rich Lanea06d0c32013-03-25 08:52:03 -0700640 debug("Type mismatch for key %s in oxm data: %s vs %s" %
Rich Lane883919c2013-05-09 17:53:18 -0700641 (key, of_match_members[key]["m_type"], oxm_type))
Rich Lanea06d0c32013-03-25 08:52:03 -0700642 sys.exit(1)