blob: 42c0a9ea4c3d865a2de466e9bf4d434660ccdef5 [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",
150 m_type="uint32_t",
151 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",
159 m_type="uint32_t",
160 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 ),
397)
398
399match_keys_sorted = of_match_members.keys()
400match_keys_sorted.sort(key=lambda entry:of_match_members[entry]["order"])
401
402of_v1_keys = [
403 "eth_dst",
404 "eth_src",
405 "eth_type",
406 "in_port",
407 "ipv4_dst",
408 "ip_proto",
409 "ipv4_src",
410 "ip_dscp",
411 "tcp_dst", # Means UDP too for 1.0 and 1.1
412 "tcp_src", # Means UDP too for 1.0 and 1.1
413 "vlan_pcp",
Rob Sherwood53989c82013-07-03 16:49:50 -0700414 "vlan_vid"
Rich Lanea06d0c32013-03-25 08:52:03 -0700415 ]
416
417of_v2_keys = [
418 "eth_dst",
419 "eth_src",
420 "eth_type",
421 "in_port",
422 "ipv4_dst",
423 "ip_proto",
424 "ipv4_src",
425 "ip_dscp",
426 "tcp_dst", # Means UDP too for 1.0 and 1.1
427 "tcp_src", # Means UDP too for 1.0 and 1.1
428 "vlan_pcp",
429 "vlan_vid",
430 "mpls_label",
431 "mpls_tc",
432 "metadata"
433 ]
434
435of_v2_full_mask = [
436 "eth_dst",
437 "eth_src",
438 "ipv4_dst",
439 "ipv4_src",
440 "metadata"
441 ]
442
443def oxm_index(key):
444 """
445 What's the index called for a match key
446 """
447 return "OF_OXM_INDEX_" + key.upper()
448
449##
450# Check that all members in the hash are recognized as match keys
451def match_sanity_check():
452 count = 0
453 for match_v in ["of_match_v1", "of_match_v2"]:
454 count += 1
455 for mm in of_g.unified[match_v][count]["members"]:
456 key = mm["name"]
457 if key.find("_mask") >= 0:
458 continue
459 if loxi_utils.skip_member_name(key):
460 continue
461 if key == "wildcards":
462 continue
463 if not key in of_match_members:
464 print "Key %s not found in match struct, v %s" % (key, match_v)
465 sys.exit(1)
466
Rich Lane883919c2013-05-09 17:53:18 -0700467 # Generate list of OXM names from the unified classes
468 oxm_names = [x[7:] for x in of_g.unified.keys() if
469 x.startswith('of_oxm_') and
470 x.find('masked') < 0 and
471 x.find('header') < 0]
472
473 # Check that all OXMs are in the match members
474 for key in oxm_names:
Rich Lanea06d0c32013-03-25 08:52:03 -0700475 if not key in of_match_members:
476 if not (key.find("_masked") > 0):
Rich Lane883919c2013-05-09 17:53:18 -0700477 debug("Key %s in OXM, not of_match_members" % key)
Rich Lanea06d0c32013-03-25 08:52:03 -0700478 sys.exit(1)
479 if not key[:-7] in of_match_members:
Rich Lane883919c2013-05-09 17:53:18 -0700480 debug("Key %s in OXM, but %s not in of_match_members"
Rich Lanea06d0c32013-03-25 08:52:03 -0700481 % (key, key[:-7]))
482 sys.exit(1)
483
Rich Lane883919c2013-05-09 17:53:18 -0700484 # Check that all match members are in the OXMs
Rich Lanea06d0c32013-03-25 08:52:03 -0700485 for key in of_match_members:
Rich Lane883919c2013-05-09 17:53:18 -0700486 if not key in oxm_names:
487 debug("Key %s in of_match_members, not in OXM" % key)
Rich Lanea06d0c32013-03-25 08:52:03 -0700488 sys.exit(1)
Rich Lane883919c2013-05-09 17:53:18 -0700489 oxm_type = of_g.unified['of_oxm_%s' % key]['union']['value']['m_type']
490 if of_match_members[key]["m_type"] != oxm_type:
Rich Lanea06d0c32013-03-25 08:52:03 -0700491 debug("Type mismatch for key %s in oxm data: %s vs %s" %
Rich Lane883919c2013-05-09 17:53:18 -0700492 (key, of_match_members[key]["m_type"], oxm_type))
Rich Lanea06d0c32013-03-25 08:52:03 -0700493 sys.exit(1)
494
495