blob: 3705e414dfe20004ccb2e7bb01956ca73b1851c3 [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():
142 count = 0
143 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:
172 match_keys[version.wire_version].append(name)
173
174 match_keys_sorted.extend(of_match_members.keys())
175 match_keys_sorted.sort(key=lambda entry:of_match_members[entry]["order"])
176
Rich Lanea06d0c32013-03-25 08:52:03 -0700177##
178# Check that all members in the hash are recognized as match keys
179def match_sanity_check():
180 count = 0
181 for match_v in ["of_match_v1", "of_match_v2"]:
182 count += 1
183 for mm in of_g.unified[match_v][count]["members"]:
184 key = mm["name"]
185 if key.find("_mask") >= 0:
186 continue
187 if loxi_utils.skip_member_name(key):
188 continue
189 if key == "wildcards":
190 continue
191 if not key in of_match_members:
192 print "Key %s not found in match struct, v %s" % (key, match_v)
193 sys.exit(1)
194
Rich Lane883919c2013-05-09 17:53:18 -0700195 # Generate list of OXM names from the unified classes
196 oxm_names = [x[7:] for x in of_g.unified.keys() if
197 x.startswith('of_oxm_') and
198 x.find('masked') < 0 and
199 x.find('header') < 0]
200
201 # Check that all OXMs are in the match members
202 for key in oxm_names:
Rich Lanea06d0c32013-03-25 08:52:03 -0700203 if not key in of_match_members:
204 if not (key.find("_masked") > 0):
Rich Lane883919c2013-05-09 17:53:18 -0700205 debug("Key %s in OXM, not of_match_members" % key)
Rich Lanea06d0c32013-03-25 08:52:03 -0700206 sys.exit(1)
207 if not key[:-7] in of_match_members:
Rich Lane883919c2013-05-09 17:53:18 -0700208 debug("Key %s in OXM, but %s not in of_match_members"
Rich Lanea06d0c32013-03-25 08:52:03 -0700209 % (key, key[:-7]))
210 sys.exit(1)
211
Rich Lane883919c2013-05-09 17:53:18 -0700212 # Check that all match members are in the OXMs
Rich Lanea06d0c32013-03-25 08:52:03 -0700213 for key in of_match_members:
Rich Lane883919c2013-05-09 17:53:18 -0700214 if not key in oxm_names:
215 debug("Key %s in of_match_members, not in OXM" % key)
Rich Lanea06d0c32013-03-25 08:52:03 -0700216 sys.exit(1)
Rich Lane883919c2013-05-09 17:53:18 -0700217 oxm_type = of_g.unified['of_oxm_%s' % key]['union']['value']['m_type']
218 if of_match_members[key]["m_type"] != oxm_type:
Rich Lanea06d0c32013-03-25 08:52:03 -0700219 debug("Type mismatch for key %s in oxm data: %s vs %s" %
Rich Lane883919c2013-05-09 17:53:18 -0700220 (key, of_match_members[key]["m_type"], oxm_type))
Rich Lanea06d0c32013-03-25 08:52:03 -0700221 sys.exit(1)