blob: 611a80d0ff0b630c8bff0b72f49dbf2294eff400 [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 Lanea06d0c32013-03-25 08:52:03 -0700462)
463
464match_keys_sorted = of_match_members.keys()
465match_keys_sorted.sort(key=lambda entry:of_match_members[entry]["order"])
466
467of_v1_keys = [
468 "eth_dst",
469 "eth_src",
470 "eth_type",
471 "in_port",
472 "ipv4_dst",
473 "ip_proto",
474 "ipv4_src",
475 "ip_dscp",
476 "tcp_dst", # Means UDP too for 1.0 and 1.1
477 "tcp_src", # Means UDP too for 1.0 and 1.1
478 "vlan_pcp",
Rob Sherwood53989c82013-07-03 16:49:50 -0700479 "vlan_vid"
Rich Lanea06d0c32013-03-25 08:52:03 -0700480 ]
481
482of_v2_keys = [
483 "eth_dst",
484 "eth_src",
485 "eth_type",
486 "in_port",
487 "ipv4_dst",
488 "ip_proto",
489 "ipv4_src",
490 "ip_dscp",
491 "tcp_dst", # Means UDP too for 1.0 and 1.1
492 "tcp_src", # Means UDP too for 1.0 and 1.1
493 "vlan_pcp",
494 "vlan_vid",
495 "mpls_label",
496 "mpls_tc",
497 "metadata"
498 ]
499
500of_v2_full_mask = [
501 "eth_dst",
502 "eth_src",
503 "ipv4_dst",
504 "ipv4_src",
505 "metadata"
506 ]
507
508def oxm_index(key):
509 """
510 What's the index called for a match key
511 """
512 return "OF_OXM_INDEX_" + key.upper()
513
514##
515# Check that all members in the hash are recognized as match keys
516def match_sanity_check():
517 count = 0
518 for match_v in ["of_match_v1", "of_match_v2"]:
519 count += 1
520 for mm in of_g.unified[match_v][count]["members"]:
521 key = mm["name"]
522 if key.find("_mask") >= 0:
523 continue
524 if loxi_utils.skip_member_name(key):
525 continue
526 if key == "wildcards":
527 continue
528 if not key in of_match_members:
529 print "Key %s not found in match struct, v %s" % (key, match_v)
530 sys.exit(1)
531
Rich Lane883919c2013-05-09 17:53:18 -0700532 # Generate list of OXM names from the unified classes
533 oxm_names = [x[7:] for x in of_g.unified.keys() if
534 x.startswith('of_oxm_') and
535 x.find('masked') < 0 and
536 x.find('header') < 0]
537
538 # Check that all OXMs are in the match members
539 for key in oxm_names:
Rich Lanea06d0c32013-03-25 08:52:03 -0700540 if not key in of_match_members:
541 if not (key.find("_masked") > 0):
Rich Lane883919c2013-05-09 17:53:18 -0700542 debug("Key %s in OXM, not of_match_members" % key)
Rich Lanea06d0c32013-03-25 08:52:03 -0700543 sys.exit(1)
544 if not key[:-7] in of_match_members:
Rich Lane883919c2013-05-09 17:53:18 -0700545 debug("Key %s in OXM, but %s not in of_match_members"
Rich Lanea06d0c32013-03-25 08:52:03 -0700546 % (key, key[:-7]))
547 sys.exit(1)
548
Rich Lane883919c2013-05-09 17:53:18 -0700549 # Check that all match members are in the OXMs
Rich Lanea06d0c32013-03-25 08:52:03 -0700550 for key in of_match_members:
Rich Lane883919c2013-05-09 17:53:18 -0700551 if not key in oxm_names:
552 debug("Key %s in of_match_members, not in OXM" % key)
Rich Lanea06d0c32013-03-25 08:52:03 -0700553 sys.exit(1)
Rich Lane883919c2013-05-09 17:53:18 -0700554 oxm_type = of_g.unified['of_oxm_%s' % key]['union']['value']['m_type']
555 if of_match_members[key]["m_type"] != oxm_type:
Rich Lanea06d0c32013-03-25 08:52:03 -0700556 debug("Type mismatch for key %s in oxm data: %s vs %s" %
Rich Lane883919c2013-05-09 17:53:18 -0700557 (key, of_match_members[key]["m_type"], oxm_type))
Rich Lanea06d0c32013-03-25 08:52:03 -0700558 sys.exit(1)