blob: d6b43fa4a3d0fc2430dab3b2970f1d7562303ea5 [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 Laneb4a63a52014-05-22 14:41:57 -070036import loxi_globals
Rich Lanea06d0c32013-03-25 08:52:03 -070037
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
Rich Lanea06d0c32013-03-25 08:52:03 -070051# order Used to define an order for readability
52# v1_wc_shift The WC shift in OF 1.0
53# v2_wc_shift The WC shift in OF 1.1
54#
Rich Lanea06d0c32013-03-25 08:52:03 -070055# We use the 1.2 names and alias older names
Rich Lanea06d0c32013-03-25 08:52:03 -070056
Rich Laneb4a63a52014-05-22 14:41:57 -070057of_match_members = dict()
Rich Lanea06d0c32013-03-25 08:52:03 -070058
59of_v1_keys = [
60 "eth_dst",
61 "eth_src",
62 "eth_type",
63 "in_port",
64 "ipv4_dst",
65 "ip_proto",
66 "ipv4_src",
67 "ip_dscp",
68 "tcp_dst", # Means UDP too for 1.0 and 1.1
69 "tcp_src", # Means UDP too for 1.0 and 1.1
70 "vlan_pcp",
Rob Sherwood53989c82013-07-03 16:49:50 -070071 "vlan_vid"
Rich Lanea06d0c32013-03-25 08:52:03 -070072 ]
73
Rich Laneb4a63a52014-05-22 14:41:57 -070074v1_wc_shifts = dict(
75 in_port=0,
76 vlan_vid=1,
77 eth_src=2,
78 eth_dst=3,
79 eth_type=4,
80 ip_proto=5,
81 tcp_src=6,
82 tcp_dst=7,
83 ipv4_src=8,
84 ipv4_dst=14,
85 vlan_pcp=20,
86 ip_dscp=21,
87)
88
Rich Lanea06d0c32013-03-25 08:52:03 -070089of_v2_keys = [
90 "eth_dst",
91 "eth_src",
92 "eth_type",
93 "in_port",
94 "ipv4_dst",
95 "ip_proto",
96 "ipv4_src",
97 "ip_dscp",
98 "tcp_dst", # Means UDP too for 1.0 and 1.1
99 "tcp_src", # Means UDP too for 1.0 and 1.1
100 "vlan_pcp",
101 "vlan_vid",
102 "mpls_label",
103 "mpls_tc",
104 "metadata"
105 ]
106
107of_v2_full_mask = [
108 "eth_dst",
109 "eth_src",
110 "ipv4_dst",
111 "ipv4_src",
112 "metadata"
113 ]
114
Rich Laneb4a63a52014-05-22 14:41:57 -0700115v2_wc_shifts = dict(
116 in_port=0,
117 vlan_vid=1,
118 vlan_pcp=2,
119 eth_type=3,
120 ip_dscp=4,
121 ip_proto=5,
122 tcp_src=6,
123 tcp_dst=7,
124 mpls_label=8,
125 mpls_tc=9,
126)
127
128# Map from wire version to list of match keys for that version
129match_keys = {
130 1: of_v1_keys,
131 2: of_v2_keys,
132 3: [],
133 4: [],
Rich Lane2dd17012014-10-16 09:55:10 -0700134 5: [],
Rich Laneb4a63a52014-05-22 14:41:57 -0700135}
136
137# Complete list of match keys, sorted by the standard order
138match_keys_sorted = []
139
140# Generate the of_match_members, match_keys, and match_keys_sorted
141# datastructures from the IR and the v1/v2 tables above
142def build():
Rich Laneb4a63a52014-05-22 14:41:57 -0700143 for uclass in loxi_globals.unified.classes:
144 if not uclass.is_oxm or uclass.name == 'of_oxm':
145 continue
146 if uclass.name.endswith('_masked'):
147 continue
148
149 name = uclass.name[7:] # of_oxm_*
150 value_member = uclass.member_by_name('value')
151 type_len = uclass.member_by_name('type_len').value
152
153 # Order match keys by their type_len
154 if (type_len & 0xffff0000) == 0x80000000:
155 # OpenFlow Basic comes first
156 order = type_len & 0x0000ffff
157 else:
158 order = type_len
159
160 match_member = dict(
161 name=name,
162 m_type=value_member.oftype,
163 order=order)
164 if name in v1_wc_shifts:
165 match_member['v1_wc_shift'] = v1_wc_shifts[name]
166 if name in v2_wc_shifts:
167 match_member['v2_wc_shift'] = v2_wc_shifts[name]
168
169 of_match_members[name] = match_member
170
171 for version in uclass.version_classes:
Rich Lanef42da582014-05-23 09:57:35 -0700172 assert name not in match_keys[version.wire_version]
Rich Laneb4a63a52014-05-22 14:41:57 -0700173 match_keys[version.wire_version].append(name)
174
Rich Lanef42da582014-05-23 09:57:35 -0700175 match_keys_sorted.extend(
176 sorted(of_match_members.keys(),
177 key=lambda entry:of_match_members[entry]["order"]))
Rich Laneb4a63a52014-05-22 14:41:57 -0700178
Rich Lanea06d0c32013-03-25 08:52:03 -0700179##
180# Check that all members in the hash are recognized as match keys
181def match_sanity_check():
182 count = 0
183 for match_v in ["of_match_v1", "of_match_v2"]:
184 count += 1
185 for mm in of_g.unified[match_v][count]["members"]:
186 key = mm["name"]
187 if key.find("_mask") >= 0:
188 continue
189 if loxi_utils.skip_member_name(key):
190 continue
191 if key == "wildcards":
192 continue
193 if not key in of_match_members:
194 print "Key %s not found in match struct, v %s" % (key, match_v)
195 sys.exit(1)
196
Rich Lane883919c2013-05-09 17:53:18 -0700197 # Generate list of OXM names from the unified classes
198 oxm_names = [x[7:] for x in of_g.unified.keys() if
199 x.startswith('of_oxm_') and
200 x.find('masked') < 0 and
201 x.find('header') < 0]
202
203 # Check that all OXMs are in the match members
204 for key in oxm_names:
Rich Lanea06d0c32013-03-25 08:52:03 -0700205 if not key in of_match_members:
206 if not (key.find("_masked") > 0):
Rich Lane883919c2013-05-09 17:53:18 -0700207 debug("Key %s in OXM, not of_match_members" % key)
Rich Lanea06d0c32013-03-25 08:52:03 -0700208 sys.exit(1)
209 if not key[:-7] in of_match_members:
Rich Lane883919c2013-05-09 17:53:18 -0700210 debug("Key %s in OXM, but %s not in of_match_members"
Rich Lanea06d0c32013-03-25 08:52:03 -0700211 % (key, key[:-7]))
212 sys.exit(1)
213
Rich Lane883919c2013-05-09 17:53:18 -0700214 # Check that all match members are in the OXMs
Rich Lanea06d0c32013-03-25 08:52:03 -0700215 for key in of_match_members:
Rich Lane883919c2013-05-09 17:53:18 -0700216 if not key in oxm_names:
217 debug("Key %s in of_match_members, not in OXM" % key)
Rich Lanea06d0c32013-03-25 08:52:03 -0700218 sys.exit(1)
Rich Lane883919c2013-05-09 17:53:18 -0700219 oxm_type = of_g.unified['of_oxm_%s' % key]['union']['value']['m_type']
220 if of_match_members[key]["m_type"] != oxm_type:
Rich Lanea06d0c32013-03-25 08:52:03 -0700221 debug("Type mismatch for key %s in oxm data: %s vs %s" %
Rich Lane883919c2013-05-09 17:53:18 -0700222 (key, of_match_members[key]["m_type"], oxm_type))
Rich Lanea06d0c32013-03-25 08:52:03 -0700223 sys.exit(1)