blob: abb70ac301f2192c35417c23a1a7f6e482aff53e [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 *
35import oxm
36import loxi_utils.loxi_utils as loxi_utils
37
38#
39# Use 1.2 match semantics for common case
40#
41# Generate maps between generic match and version specific matches
42# Generate dump functions for generic match
43# Generate dump functions for version specific matches
44
45## @var of_match_members
46# The dictionary from unified match members to type and indexing info
47#
48# Keys:
49# name The unified name used for the member
50# m_type The data type used for the object in unified structure
51# print_type The id to use when printing
52# conditions The condition underwhich the field could occur TBD
53# takes_mask_in_spec Shown as taking mask in OF 1.2 spec; IGNORED NOW
54# order Used to define an order for readability
55# v1_wc_shift The WC shift in OF 1.0
56# v2_wc_shift The WC shift in OF 1.1
57#
58# Unless noted otherwise, class is 0x8000, OFPXMC_OPENFLOW_BASIC
59# We use the 1.2 names and alias older names
60# Conditions:
61# is_ipv4(_m): ((_m)->eth_type == 0x0800)
62# is_ipv6(_m): ((_m)->eth_type == 0x86dd)
63# is_ip(_m): (is_ipv4(_m) || is_ipv6(_m))
64# is_arp(_m): ((_m)->eth_type == 0x0806)
65# is_tcp(_m): (is_ip(_m) && ((_m)->ip_proto == 6))
66# is_udp(_m): (is_ip(_m) && ((_m)->ip_proto == 17))
67# is_sctp(_m): (is_ip(_m) && ((_m)->ip_proto == 132))
68# is_icmpv4(_m): (is_ipv4(_m) && ((_m)->ip_proto == 1))
69# is_icmpv6(_m): (is_ipv6(_m) && ((_m)->ip_proto == 58))
70#
71
72of_match_members = dict(
73 in_port = dict(
74 name="in_port",
75 m_type="of_port_no_t",
76 print_type="PRIx32",
77 conditions="",
78 v1_wc_shift=0,
79 v2_wc_shift=0,
80 takes_mask_in_spec=False,
81 order=100,
82 ),
83 in_phy_port = dict(
84 name="in_phy_port",
85 m_type="of_port_no_t",
86 print_type="PRIx32",
87 conditions="", # OXM_OF_IN_PORT must be present
88 takes_mask_in_spec=False,
89 order=101,
90 ),
91 metadata = dict(
92 name="metadata",
93 m_type="uint64_t",
94 print_type="PRIx64",
95 conditions="",
96 takes_mask_in_spec=True,
97 order=102,
98 ),
99
100 eth_dst = dict(
101 name="eth_dst",
102 m_type="of_mac_addr_t",
103 v1_wc_shift=3,
104 print_type="\"p\"",
105 conditions="",
106 takes_mask_in_spec=True,
107 order=200,
108 ),
109 eth_src = dict(
110 name="eth_src",
111 m_type="of_mac_addr_t",
112 v1_wc_shift=2,
113 print_type="\"p\"",
114 conditions="",
115 takes_mask_in_spec=True,
116 order=201,
117 ),
118 eth_type = dict(
119 name="eth_type",
120 m_type="uint16_t",
121 v1_wc_shift=4,
122 v2_wc_shift=3,
123 print_type="PRIx16",
124 conditions="",
125 takes_mask_in_spec=False,
126 order=203,
127 ),
128 vlan_vid = dict( # FIXME: Semantics changed in 1.2
129 # Use CFI bit to indicate tag presence
130 name="vlan_vid",
131 m_type="uint16_t",
132 v1_wc_shift=1,
133 v2_wc_shift=1,
134 print_type="PRIx16",
135 conditions="",
136 takes_mask_in_spec=True,
137 order=210,
138 ),
139 vlan_pcp = dict(
140 name="vlan_pcp",
141 m_type="uint8_t",
142 v1_wc_shift=20,
143 v2_wc_shift=2,
144 print_type="PRIx8",
145 conditions="",
146 takes_mask_in_spec=False,
147 order=211,
148 ),
149 ipv4_src = dict(
150 name="ipv4_src",
151 m_type="uint32_t",
152 v1_wc_shift=8,
153 print_type="PRIx32",
154 conditions="is_ipv4(match)",
155 takes_mask_in_spec=True,
156 order=300,
157 ),
158 ipv4_dst = dict(
159 name="ipv4_dst",
160 m_type="uint32_t",
161 v1_wc_shift=14,
162 print_type="PRIx32",
163 conditions="is_ipv4(match)",
164 takes_mask_in_spec=True,
165 order=301,
166 ),
167 ip_dscp = dict(
168 name="ip_dscp",
169 m_type="uint8_t",
170 v1_wc_shift=21,
171 v2_wc_shift=4,
172 print_type="PRIx8",
173 conditions="is_ip(match)",
174 takes_mask_in_spec=False,
175 order=310,
176 ),
177 ip_ecn = dict(
178 name="ip_ecn",
179 m_type="uint8_t",
180 print_type="PRIx8",
181 conditions="is_ip(match)",
182 takes_mask_in_spec=False,
183 order=311,
184 ),
185 ip_proto = dict(
186 name="ip_proto",
187 m_type="uint8_t",
188 v1_wc_shift=5,
189 v2_wc_shift=5,
190 print_type="PRIx8",
191 conditions="is_ip(match)",
192 takes_mask_in_spec=False,
193 order=320,
194 ),
195
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,
274 order=250,
275 ),
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,
283 order=251,
284 ),
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,
291 order=252,
292 ),
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,
300 order=253,
301 ),
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,
308 order=254,
309 ),
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,
317 order=350,
318 ),
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,
325 order=351,
326 ),
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
334 order=360,
335 ),
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,
343 order=440,
344 ),
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,
351 order=441,
352 ),
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,
360 order=442,
361 ),
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,
369 order=443,
370 ),
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,
377 order=444,
378 ),
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,
387 order=500,
388 ),
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,
396 order=501,
397 ),
398)
399
400match_keys_sorted = of_match_members.keys()
401match_keys_sorted.sort(key=lambda entry:of_match_members[entry]["order"])
402
403of_v1_keys = [
404 "eth_dst",
405 "eth_src",
406 "eth_type",
407 "in_port",
408 "ipv4_dst",
409 "ip_proto",
410 "ipv4_src",
411 "ip_dscp",
412 "tcp_dst", # Means UDP too for 1.0 and 1.1
413 "tcp_src", # Means UDP too for 1.0 and 1.1
414 "vlan_pcp",
415 "vlan_vid"
416 ]
417
418of_v2_keys = [
419 "eth_dst",
420 "eth_src",
421 "eth_type",
422 "in_port",
423 "ipv4_dst",
424 "ip_proto",
425 "ipv4_src",
426 "ip_dscp",
427 "tcp_dst", # Means UDP too for 1.0 and 1.1
428 "tcp_src", # Means UDP too for 1.0 and 1.1
429 "vlan_pcp",
430 "vlan_vid",
431 "mpls_label",
432 "mpls_tc",
433 "metadata"
434 ]
435
436of_v2_full_mask = [
437 "eth_dst",
438 "eth_src",
439 "ipv4_dst",
440 "ipv4_src",
441 "metadata"
442 ]
443
444def oxm_index(key):
445 """
446 What's the index called for a match key
447 """
448 return "OF_OXM_INDEX_" + key.upper()
449
450##
451# Check that all members in the hash are recognized as match keys
452def match_sanity_check():
453 count = 0
454 for match_v in ["of_match_v1", "of_match_v2"]:
455 count += 1
456 for mm in of_g.unified[match_v][count]["members"]:
457 key = mm["name"]
458 if key.find("_mask") >= 0:
459 continue
460 if loxi_utils.skip_member_name(key):
461 continue
462 if key == "wildcards":
463 continue
464 if not key in of_match_members:
465 print "Key %s not found in match struct, v %s" % (key, match_v)
466 sys.exit(1)
467
Rich Lane883919c2013-05-09 17:53:18 -0700468 # Generate list of OXM names from the unified classes
469 oxm_names = [x[7:] for x in of_g.unified.keys() if
470 x.startswith('of_oxm_') and
471 x.find('masked') < 0 and
472 x.find('header') < 0]
473
474 # Check that all OXMs are in the match members
475 for key in oxm_names:
Rich Lanea06d0c32013-03-25 08:52:03 -0700476 if not key in of_match_members:
477 if not (key.find("_masked") > 0):
Rich Lane883919c2013-05-09 17:53:18 -0700478 debug("Key %s in OXM, not of_match_members" % key)
Rich Lanea06d0c32013-03-25 08:52:03 -0700479 sys.exit(1)
480 if not key[:-7] in of_match_members:
Rich Lane883919c2013-05-09 17:53:18 -0700481 debug("Key %s in OXM, but %s not in of_match_members"
Rich Lanea06d0c32013-03-25 08:52:03 -0700482 % (key, key[:-7]))
483 sys.exit(1)
484
Rich Lane883919c2013-05-09 17:53:18 -0700485 # Check that all match members are in the OXMs
Rich Lanea06d0c32013-03-25 08:52:03 -0700486 for key in of_match_members:
Rich Lane883919c2013-05-09 17:53:18 -0700487 if not key in oxm_names:
488 debug("Key %s in of_match_members, not in OXM" % key)
Rich Lanea06d0c32013-03-25 08:52:03 -0700489 sys.exit(1)
Rich Lane883919c2013-05-09 17:53:18 -0700490 oxm_type = of_g.unified['of_oxm_%s' % key]['union']['value']['m_type']
491 if of_match_members[key]["m_type"] != oxm_type:
Rich Lanea06d0c32013-03-25 08:52:03 -0700492 debug("Type mismatch for key %s in oxm data: %s vs %s" %
Rich Lane883919c2013-05-09 17:53:18 -0700493 (key, of_match_members[key]["m_type"], oxm_type))
Rich Lanea06d0c32013-03-25 08:52:03 -0700494 sys.exit(1)
495
496