blob: c5104779f5cd9e7b3a10a99ec14da704bddde95d [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
33import of_g
34from generic_utils import *
Rich Lanea06d0c32013-03-25 08:52:03 -070035import loxi_utils.loxi_utils as loxi_utils
36
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 ),
148 ipv4_src = dict(
149 name="ipv4_src",
Andreas Wundsamb566a162013-07-18 19:30:23 -0700150 m_type="of_ipv4_t",
Rich Lanea06d0c32013-03-25 08:52:03 -0700151 v1_wc_shift=8,
152 print_type="PRIx32",
153 conditions="is_ipv4(match)",
154 takes_mask_in_spec=True,
155 order=300,
156 ),
157 ipv4_dst = dict(
158 name="ipv4_dst",
Andreas Wundsamb566a162013-07-18 19:30:23 -0700159 m_type="of_ipv4_t",
Rich Lanea06d0c32013-03-25 08:52:03 -0700160 v1_wc_shift=14,
161 print_type="PRIx32",
162 conditions="is_ipv4(match)",
163 takes_mask_in_spec=True,
164 order=301,
165 ),
166 ip_dscp = dict(
167 name="ip_dscp",
168 m_type="uint8_t",
169 v1_wc_shift=21,
170 v2_wc_shift=4,
171 print_type="PRIx8",
172 conditions="is_ip(match)",
173 takes_mask_in_spec=False,
174 order=310,
175 ),
176 ip_ecn = dict(
177 name="ip_ecn",
178 m_type="uint8_t",
179 print_type="PRIx8",
180 conditions="is_ip(match)",
181 takes_mask_in_spec=False,
182 order=311,
183 ),
184 ip_proto = dict(
185 name="ip_proto",
186 m_type="uint8_t",
187 v1_wc_shift=5,
188 v2_wc_shift=5,
189 print_type="PRIx8",
190 conditions="is_ip(match)",
191 takes_mask_in_spec=False,
192 order=320,
193 ),
194
195 tcp_dst = dict(
196 name="tcp_dst",
197 m_type="uint16_t",
198 v1_wc_shift=7,
199 v2_wc_shift=7,
200 print_type="PRIx16",
201 conditions="is_tcp(match)",
202 takes_mask_in_spec=False,
203 order=400,
204 ),
205 tcp_src = dict(
206 name="tcp_src",
207 m_type="uint16_t",
208 v1_wc_shift=6,
209 v2_wc_shift=6,
210 print_type="PRIx16",
211 conditions="is_tcp(match)",
212 takes_mask_in_spec=False,
213 order=401,
214 ),
215
216 udp_dst = dict(
217 name="udp_dst",
218 m_type="uint16_t",
219 print_type="PRIx16",
220 conditions="is_udp(match)",
221 takes_mask_in_spec=False,
222 order=410,
223 ),
224 udp_src = dict(
225 name="udp_src",
226 m_type="uint16_t",
227 print_type="PRIx16",
228 conditions="is_udp(match)",
229 takes_mask_in_spec=False,
230 order=411,
231 ),
232
233 sctp_dst = dict(
234 name="sctp_dst",
235 m_type="uint16_t",
236 print_type="PRIx16",
237 conditions="is_sctp(match)",
238 takes_mask_in_spec=False,
239 order=420,
240 ),
241 sctp_src = dict(
242 name="sctp_src",
243 m_type="uint16_t",
244 print_type="PRIx16",
245 conditions="is_sctp(match)",
246 takes_mask_in_spec=False,
247 order=421,
248 ),
249
250 icmpv4_type = dict(
251 name="icmpv4_type",
252 m_type="uint8_t",
253 print_type="PRIx8",
254 conditions="is_icmp_v4(match)",
255 takes_mask_in_spec=False,
256 order=430,
257 ),
258 icmpv4_code = dict(
259 name="icmpv4_code",
260 m_type="uint8_t",
261 print_type="PRIx8",
262 conditions="is_icmp_v4(match)",
263 takes_mask_in_spec=False,
264 order=431,
265 ),
266
267 arp_op = dict(
268 name="arp_op",
269 m_type="uint16_t",
270 print_type="PRIx16",
271 conditions="is_arp(match)",
272 takes_mask_in_spec=False,
273 order=250,
274 ),
275
276 arp_spa = dict(
277 name="arp_spa",
278 m_type="uint32_t",
279 print_type="PRIx32",
280 conditions="is_arp(match)",
281 takes_mask_in_spec=True,
282 order=251,
283 ),
284 arp_tpa = dict(
285 name="arp_tpa",
286 m_type="uint32_t",
287 print_type="PRIx32",
288 conditions="is_arp(match)",
289 takes_mask_in_spec=True,
290 order=252,
291 ),
292
293 arp_sha = dict(
294 name="arp_sha",
295 m_type="of_mac_addr_t",
296 print_type="\"p\"",
297 conditions="is_arp(match)",
298 takes_mask_in_spec=False,
299 order=253,
300 ),
301 arp_tha = dict(
302 name="arp_tha",
303 m_type="of_mac_addr_t",
304 print_type="\"p\"",
305 conditions="is_arp(match)",
306 takes_mask_in_spec=False,
307 order=254,
308 ),
309
310 ipv6_src = dict(
311 name="ipv6_src",
312 m_type="of_ipv6_t",
313 print_type="\"p\"",
314 conditions="is_ipv6(match)",
315 takes_mask_in_spec=True,
316 order=350,
317 ),
318 ipv6_dst = dict(
319 name="ipv6_dst",
320 m_type="of_ipv6_t",
321 print_type="\"p\"",
322 conditions="is_ipv6(match)",
323 takes_mask_in_spec=True,
324 order=351,
325 ),
326
327 ipv6_flabel = dict(
328 name="ipv6_flabel",
329 m_type="uint32_t",
330 print_type="PRIx32",
331 conditions="is_ipv6(match)",
332 takes_mask_in_spec=False, # Comment in openflow.h says True
333 order=360,
334 ),
335
336 icmpv6_type = dict(
337 name="icmpv6_type",
338 m_type="uint8_t",
339 print_type="PRIx8",
340 conditions="is_icmp_v6(match)",
341 takes_mask_in_spec=False,
342 order=440,
343 ),
344 icmpv6_code = dict(
345 name="icmpv6_code",
346 m_type="uint8_t",
347 print_type="PRIx8",
348 conditions="is_icmp_v6(match)",
349 takes_mask_in_spec=False,
350 order=441,
351 ),
352
353 ipv6_nd_target = dict(
354 name="ipv6_nd_target",
355 m_type="of_ipv6_t",
356 print_type="\"p\"",
357 conditions="", # fixme
358 takes_mask_in_spec=False,
359 order=442,
360 ),
361
362 ipv6_nd_sll = dict(
363 name="ipv6_nd_sll",
364 m_type="of_mac_addr_t",
365 print_type="\"p\"",
366 conditions="", # fixme
367 takes_mask_in_spec=False,
368 order=443,
369 ),
370 ipv6_nd_tll = dict(
371 name="ipv6_nd_tll",
372 m_type="of_mac_addr_t",
373 print_type="\"p\"",
374 conditions="", # fixme
375 takes_mask_in_spec=False,
376 order=444,
377 ),
378
379 mpls_label = dict(
380 name="mpls_label",
381 m_type="uint32_t",
382 v2_wc_shift=8,
383 print_type="PRIx32",
384 conditions="",
385 takes_mask_in_spec=False,
386 order=500,
387 ),
388 mpls_tc = dict(
389 name="mpls_tc",
390 m_type="uint8_t",
391 v2_wc_shift=9,
392 print_type="PRIx8",
393 conditions="",
394 takes_mask_in_spec=False,
395 order=501,
396 ),
Rich Laned8d29c92013-09-24 13:46:42 -0700397
398 bsn_in_ports_128 = dict(
399 name="bsn_in_ports_128",
400 m_type="of_bitmap_128_t",
401 v2_wc_shift=9,
402 print_type="p",
403 conditions="",
404 takes_mask_in_spec=True,
405 order=1000,
406 ),
Rich Lanea06d0c32013-03-25 08:52:03 -0700407)
408
409match_keys_sorted = of_match_members.keys()
410match_keys_sorted.sort(key=lambda entry:of_match_members[entry]["order"])
411
412of_v1_keys = [
413 "eth_dst",
414 "eth_src",
415 "eth_type",
416 "in_port",
417 "ipv4_dst",
418 "ip_proto",
419 "ipv4_src",
420 "ip_dscp",
421 "tcp_dst", # Means UDP too for 1.0 and 1.1
422 "tcp_src", # Means UDP too for 1.0 and 1.1
423 "vlan_pcp",
Rob Sherwood53989c82013-07-03 16:49:50 -0700424 "vlan_vid"
Rich Lanea06d0c32013-03-25 08:52:03 -0700425 ]
426
427of_v2_keys = [
428 "eth_dst",
429 "eth_src",
430 "eth_type",
431 "in_port",
432 "ipv4_dst",
433 "ip_proto",
434 "ipv4_src",
435 "ip_dscp",
436 "tcp_dst", # Means UDP too for 1.0 and 1.1
437 "tcp_src", # Means UDP too for 1.0 and 1.1
438 "vlan_pcp",
439 "vlan_vid",
440 "mpls_label",
441 "mpls_tc",
442 "metadata"
443 ]
444
445of_v2_full_mask = [
446 "eth_dst",
447 "eth_src",
448 "ipv4_dst",
449 "ipv4_src",
450 "metadata"
451 ]
452
453def oxm_index(key):
454 """
455 What's the index called for a match key
456 """
457 return "OF_OXM_INDEX_" + key.upper()
458
459##
460# Check that all members in the hash are recognized as match keys
461def match_sanity_check():
462 count = 0
463 for match_v in ["of_match_v1", "of_match_v2"]:
464 count += 1
465 for mm in of_g.unified[match_v][count]["members"]:
466 key = mm["name"]
467 if key.find("_mask") >= 0:
468 continue
469 if loxi_utils.skip_member_name(key):
470 continue
471 if key == "wildcards":
472 continue
473 if not key in of_match_members:
474 print "Key %s not found in match struct, v %s" % (key, match_v)
475 sys.exit(1)
476
Rich Lane883919c2013-05-09 17:53:18 -0700477 # Generate list of OXM names from the unified classes
478 oxm_names = [x[7:] for x in of_g.unified.keys() if
479 x.startswith('of_oxm_') and
480 x.find('masked') < 0 and
481 x.find('header') < 0]
482
483 # Check that all OXMs are in the match members
484 for key in oxm_names:
Rich Lanea06d0c32013-03-25 08:52:03 -0700485 if not key in of_match_members:
486 if not (key.find("_masked") > 0):
Rich Lane883919c2013-05-09 17:53:18 -0700487 debug("Key %s in OXM, not of_match_members" % key)
Rich Lanea06d0c32013-03-25 08:52:03 -0700488 sys.exit(1)
489 if not key[:-7] in of_match_members:
Rich Lane883919c2013-05-09 17:53:18 -0700490 debug("Key %s in OXM, but %s not in of_match_members"
Rich Lanea06d0c32013-03-25 08:52:03 -0700491 % (key, key[:-7]))
492 sys.exit(1)
493
Rich Lane883919c2013-05-09 17:53:18 -0700494 # Check that all match members are in the OXMs
Rich Lanea06d0c32013-03-25 08:52:03 -0700495 for key in of_match_members:
Rich Lane883919c2013-05-09 17:53:18 -0700496 if not key in oxm_names:
497 debug("Key %s in of_match_members, not in OXM" % key)
Rich Lanea06d0c32013-03-25 08:52:03 -0700498 sys.exit(1)
Rich Lane883919c2013-05-09 17:53:18 -0700499 oxm_type = of_g.unified['of_oxm_%s' % key]['union']['value']['m_type']
500 if of_match_members[key]["m_type"] != oxm_type:
Rich Lanea06d0c32013-03-25 08:52:03 -0700501 debug("Type mismatch for key %s in oxm data: %s vs %s" %
Rich Lane883919c2013-05-09 17:53:18 -0700502 (key, of_match_members[key]["m_type"], oxm_type))
Rich Lanea06d0c32013-03-25 08:52:03 -0700503 sys.exit(1)
504
505