blob: 7b7dcce3579ae585682b139874a501fdc8ee6152 [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: [],
134}
135
136# Complete list of match keys, sorted by the standard order
137match_keys_sorted = []
138
139# Generate the of_match_members, match_keys, and match_keys_sorted
140# datastructures from the IR and the v1/v2 tables above
141def build():
Rich Laneb4a63a52014-05-22 14:41:57 -0700142 for uclass in loxi_globals.unified.classes:
143 if not uclass.is_oxm or uclass.name == 'of_oxm':
144 continue
145 if uclass.name.endswith('_masked'):
146 continue
147
148 name = uclass.name[7:] # of_oxm_*
149 value_member = uclass.member_by_name('value')
150 type_len = uclass.member_by_name('type_len').value
151
152 # Order match keys by their type_len
153 if (type_len & 0xffff0000) == 0x80000000:
154 # OpenFlow Basic comes first
155 order = type_len & 0x0000ffff
156 else:
157 order = type_len
158
159 match_member = dict(
160 name=name,
161 m_type=value_member.oftype,
162 order=order)
163 if name in v1_wc_shifts:
164 match_member['v1_wc_shift'] = v1_wc_shifts[name]
165 if name in v2_wc_shifts:
166 match_member['v2_wc_shift'] = v2_wc_shifts[name]
167
168 of_match_members[name] = match_member
169
170 for version in uclass.version_classes:
Rich Lanef42da582014-05-23 09:57:35 -0700171 assert name not in match_keys[version.wire_version]
Rich Laneb4a63a52014-05-22 14:41:57 -0700172 match_keys[version.wire_version].append(name)
173
Rich Lanef42da582014-05-23 09:57:35 -0700174 match_keys_sorted.extend(
175 sorted(of_match_members.keys(),
176 key=lambda entry:of_match_members[entry]["order"]))
Rich Laneb4a63a52014-05-22 14:41:57 -0700177
Rich Lanea06d0c32013-03-25 08:52:03 -0700178##
179# Check that all members in the hash are recognized as match keys
180def match_sanity_check():
181 count = 0
182 for match_v in ["of_match_v1", "of_match_v2"]:
183 count += 1
184 for mm in of_g.unified[match_v][count]["members"]:
185 key = mm["name"]
186 if key.find("_mask") >= 0:
187 continue
188 if loxi_utils.skip_member_name(key):
189 continue
190 if key == "wildcards":
191 continue
192 if not key in of_match_members:
193 print "Key %s not found in match struct, v %s" % (key, match_v)
194 sys.exit(1)
195
Rich Lane883919c2013-05-09 17:53:18 -0700196 # Generate list of OXM names from the unified classes
197 oxm_names = [x[7:] for x in of_g.unified.keys() if
198 x.startswith('of_oxm_') and
199 x.find('masked') < 0 and
200 x.find('header') < 0]
201
202 # Check that all OXMs are in the match members
203 for key in oxm_names:
Rich Lanea06d0c32013-03-25 08:52:03 -0700204 if not key in of_match_members:
205 if not (key.find("_masked") > 0):
Rich Lane883919c2013-05-09 17:53:18 -0700206 debug("Key %s in OXM, not of_match_members" % key)
Rich Lanea06d0c32013-03-25 08:52:03 -0700207 sys.exit(1)
208 if not key[:-7] in of_match_members:
Rich Lane883919c2013-05-09 17:53:18 -0700209 debug("Key %s in OXM, but %s not in of_match_members"
Rich Lanea06d0c32013-03-25 08:52:03 -0700210 % (key, key[:-7]))
211 sys.exit(1)
212
Rich Lane883919c2013-05-09 17:53:18 -0700213 # Check that all match members are in the OXMs
Rich Lanea06d0c32013-03-25 08:52:03 -0700214 for key in of_match_members:
Rich Lane883919c2013-05-09 17:53:18 -0700215 if not key in oxm_names:
216 debug("Key %s in of_match_members, not in OXM" % key)
Rich Lanea06d0c32013-03-25 08:52:03 -0700217 sys.exit(1)
Rich Lane883919c2013-05-09 17:53:18 -0700218 oxm_type = of_g.unified['of_oxm_%s' % key]['union']['value']['m_type']
219 if of_match_members[key]["m_type"] != oxm_type:
Rich Lanea06d0c32013-03-25 08:52:03 -0700220 debug("Type mismatch for key %s in oxm data: %s vs %s" %
Rich Lane883919c2013-05-09 17:53:18 -0700221 (key, of_match_members[key]["m_type"], oxm_type))
Rich Lanea06d0c32013-03-25 08:52:03 -0700222 sys.exit(1)