1 /*
2  * drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c
3  * Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved.
4  * Copyright (c) 2017-2018 Jiri Pirko <jiri@mellanox.com>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. Neither the names of the copyright holders nor the names of its
15  *    contributors may be used to endorse or promote products derived from
16  *    this software without specific prior written permission.
17  *
18  * Alternatively, this software may be distributed under the terms of the
19  * GNU General Public License ("GPL") version 2 as published by the Free
20  * Software Foundation.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include <linux/kernel.h>
36 #include <linux/module.h>
37 #include "spectrum.h"
38 #include "item.h"
39 #include "core_acl_flex_keys.h"
40 
41 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_dmac[] = {
42 	MLXSW_AFK_ELEMENT_INST_BUF(DMAC_32_47, 0x00, 2),
43 	MLXSW_AFK_ELEMENT_INST_BUF(DMAC_0_31, 0x02, 4),
44 	MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x08, 13, 3),
45 	MLXSW_AFK_ELEMENT_INST_U32(VID, 0x08, 0, 12),
46 	MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 8),
47 };
48 
49 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_smac[] = {
50 	MLXSW_AFK_ELEMENT_INST_BUF(SMAC_32_47, 0x00, 2),
51 	MLXSW_AFK_ELEMENT_INST_BUF(SMAC_0_31, 0x02, 4),
52 	MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x08, 13, 3),
53 	MLXSW_AFK_ELEMENT_INST_U32(VID, 0x08, 0, 12),
54 	MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 8),
55 };
56 
57 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_smac_ex[] = {
58 	MLXSW_AFK_ELEMENT_INST_BUF(SMAC_32_47, 0x02, 2),
59 	MLXSW_AFK_ELEMENT_INST_BUF(SMAC_0_31, 0x04, 4),
60 	MLXSW_AFK_ELEMENT_INST_U32(ETHERTYPE, 0x0C, 0, 16),
61 };
62 
63 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_sip[] = {
64 	MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x00, 4),
65 	MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x08, 0, 8),
66 	MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 8),
67 };
68 
69 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_dip[] = {
70 	MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_0_31, 0x00, 4),
71 	MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x08, 0, 8),
72 	MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 8),
73 };
74 
75 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4[] = {
76 	MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x00, 4),
77 	MLXSW_AFK_ELEMENT_INST_U32(IP_ECN, 0x04, 4, 2),
78 	MLXSW_AFK_ELEMENT_INST_U32(IP_TTL_, 0x04, 24, 8),
79 	MLXSW_AFK_ELEMENT_INST_U32(IP_DSCP, 0x08, 0, 6),
80 	MLXSW_AFK_ELEMENT_INST_U32(TCP_FLAGS, 0x08, 8, 9), /* TCP_CONTROL+TCP_ECN */
81 };
82 
83 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_ex[] = {
84 	MLXSW_AFK_ELEMENT_INST_U32(VID, 0x00, 0, 12),
85 	MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x08, 29, 3),
86 	MLXSW_AFK_ELEMENT_INST_U32(SRC_L4_PORT, 0x08, 0, 16),
87 	MLXSW_AFK_ELEMENT_INST_U32(DST_L4_PORT, 0x0C, 0, 16),
88 };
89 
90 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_dip[] = {
91 	MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_32_63, 0x00, 4),
92 	MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_0_31, 0x04, 4),
93 };
94 
95 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_ex1[] = {
96 	MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_96_127, 0x00, 4),
97 	MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_64_95, 0x04, 4),
98 	MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x08, 0, 8),
99 };
100 
101 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_sip[] = {
102 	MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_32_63, 0x00, 4),
103 	MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x04, 4),
104 };
105 
106 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_sip_ex[] = {
107 	MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_96_127, 0x00, 4),
108 	MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_64_95, 0x04, 4),
109 };
110 
111 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_packet_type[] = {
112 	MLXSW_AFK_ELEMENT_INST_U32(ETHERTYPE, 0x00, 0, 16),
113 };
114 
115 static const struct mlxsw_afk_block mlxsw_sp1_afk_blocks[] = {
116 	MLXSW_AFK_BLOCK(0x10, mlxsw_sp_afk_element_info_l2_dmac),
117 	MLXSW_AFK_BLOCK(0x11, mlxsw_sp_afk_element_info_l2_smac),
118 	MLXSW_AFK_BLOCK(0x12, mlxsw_sp_afk_element_info_l2_smac_ex),
119 	MLXSW_AFK_BLOCK(0x30, mlxsw_sp_afk_element_info_ipv4_sip),
120 	MLXSW_AFK_BLOCK(0x31, mlxsw_sp_afk_element_info_ipv4_dip),
121 	MLXSW_AFK_BLOCK(0x32, mlxsw_sp_afk_element_info_ipv4),
122 	MLXSW_AFK_BLOCK(0x33, mlxsw_sp_afk_element_info_ipv4_ex),
123 	MLXSW_AFK_BLOCK(0x60, mlxsw_sp_afk_element_info_ipv6_dip),
124 	MLXSW_AFK_BLOCK(0x65, mlxsw_sp_afk_element_info_ipv6_ex1),
125 	MLXSW_AFK_BLOCK(0x62, mlxsw_sp_afk_element_info_ipv6_sip),
126 	MLXSW_AFK_BLOCK(0x63, mlxsw_sp_afk_element_info_ipv6_sip_ex),
127 	MLXSW_AFK_BLOCK(0xB0, mlxsw_sp_afk_element_info_packet_type),
128 };
129 
130 #define MLXSW_SP1_AFK_KEY_BLOCK_SIZE 16
131 
132 static void mlxsw_sp1_afk_encode_block(char *block, int block_index,
133 				       char *output)
134 {
135 	unsigned int offset = block_index * MLXSW_SP1_AFK_KEY_BLOCK_SIZE;
136 	char *output_indexed = output + offset;
137 
138 	memcpy(output_indexed, block, MLXSW_SP1_AFK_KEY_BLOCK_SIZE);
139 }
140 
141 const struct mlxsw_afk_ops mlxsw_sp1_afk_ops = {
142 	.blocks		= mlxsw_sp1_afk_blocks,
143 	.blocks_count	= ARRAY_SIZE(mlxsw_sp1_afk_blocks),
144 	.encode_block	= mlxsw_sp1_afk_encode_block,
145 };
146 
147 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_0[] = {
148 	MLXSW_AFK_ELEMENT_INST_BUF(DMAC_0_31, 0x04, 4),
149 };
150 
151 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_1[] = {
152 	MLXSW_AFK_ELEMENT_INST_BUF(SMAC_0_31, 0x04, 4),
153 };
154 
155 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_2[] = {
156 	MLXSW_AFK_ELEMENT_INST_BUF(SMAC_32_47, 0x04, 2),
157 	MLXSW_AFK_ELEMENT_INST_BUF(DMAC_32_47, 0x06, 2),
158 };
159 
160 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_3[] = {
161 	MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x00, 0, 3),
162 	MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 16, 12),
163 	MLXSW_AFK_ELEMENT_INST_BUF(DMAC_32_47, 0x06, 2),
164 };
165 
166 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_4[] = {
167 	MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x00, 0, 3),
168 	MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 16, 12),
169 	MLXSW_AFK_ELEMENT_INST_U32(ETHERTYPE, 0x04, 0, 16),
170 };
171 
172 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_5[] = {
173 	MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 16, 12),
174 	MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x04, 0, 8), /* RX_ACL_SYSTEM_PORT */
175 };
176 
177 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_0[] = {
178 	MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_0_31, 0x04, 4),
179 };
180 
181 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_1[] = {
182 	MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x04, 4),
183 };
184 
185 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_2[] = {
186 	MLXSW_AFK_ELEMENT_INST_U32(IP_DSCP, 0x04, 0, 6),
187 	MLXSW_AFK_ELEMENT_INST_U32(IP_ECN, 0x04, 6, 2),
188 	MLXSW_AFK_ELEMENT_INST_U32(IP_TTL_, 0x04, 8, 8),
189 	MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x04, 16, 8),
190 };
191 
192 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_0[] = {
193 	MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_32_63, 0x04, 4),
194 };
195 
196 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_1[] = {
197 	MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_64_95, 0x04, 4),
198 };
199 
200 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_2[] = {
201 	MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_96_127, 0x04, 4),
202 };
203 
204 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_3[] = {
205 	MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_32_63, 0x04, 4),
206 };
207 
208 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_4[] = {
209 	MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_64_95, 0x04, 4),
210 };
211 
212 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_5[] = {
213 	MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_96_127, 0x04, 4),
214 };
215 
216 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l4_0[] = {
217 	MLXSW_AFK_ELEMENT_INST_U32(SRC_L4_PORT, 0x04, 16, 16),
218 	MLXSW_AFK_ELEMENT_INST_U32(DST_L4_PORT, 0x04, 0, 16),
219 };
220 
221 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l4_2[] = {
222 	MLXSW_AFK_ELEMENT_INST_U32(TCP_FLAGS, 0x04, 16, 9), /* TCP_CONTROL + TCP_ECN */
223 };
224 
225 static const struct mlxsw_afk_block mlxsw_sp2_afk_blocks[] = {
226 	MLXSW_AFK_BLOCK(0x10, mlxsw_sp_afk_element_info_mac_0),
227 	MLXSW_AFK_BLOCK(0x11, mlxsw_sp_afk_element_info_mac_1),
228 	MLXSW_AFK_BLOCK(0x12, mlxsw_sp_afk_element_info_mac_2),
229 	MLXSW_AFK_BLOCK(0x13, mlxsw_sp_afk_element_info_mac_3),
230 	MLXSW_AFK_BLOCK(0x14, mlxsw_sp_afk_element_info_mac_4),
231 	MLXSW_AFK_BLOCK(0x15, mlxsw_sp_afk_element_info_mac_5),
232 	MLXSW_AFK_BLOCK(0x38, mlxsw_sp_afk_element_info_ipv4_0),
233 	MLXSW_AFK_BLOCK(0x39, mlxsw_sp_afk_element_info_ipv4_1),
234 	MLXSW_AFK_BLOCK(0x3A, mlxsw_sp_afk_element_info_ipv4_2),
235 	MLXSW_AFK_BLOCK(0x40, mlxsw_sp_afk_element_info_ipv6_0),
236 	MLXSW_AFK_BLOCK(0x41, mlxsw_sp_afk_element_info_ipv6_1),
237 	MLXSW_AFK_BLOCK(0x42, mlxsw_sp_afk_element_info_ipv6_2),
238 	MLXSW_AFK_BLOCK(0x43, mlxsw_sp_afk_element_info_ipv6_3),
239 	MLXSW_AFK_BLOCK(0x44, mlxsw_sp_afk_element_info_ipv6_4),
240 	MLXSW_AFK_BLOCK(0x45, mlxsw_sp_afk_element_info_ipv6_5),
241 	MLXSW_AFK_BLOCK(0x90, mlxsw_sp_afk_element_info_l4_0),
242 	MLXSW_AFK_BLOCK(0x92, mlxsw_sp_afk_element_info_l4_2),
243 };
244 
245 #define MLXSW_SP2_AFK_BITS_PER_BLOCK 36
246 
247 /* A block in Spectrum-2 is of the following form:
248  *
249  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
250  * |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |35|34|33|32|
251  * +-----------------------------------------------------------------------------------------------+
252  * |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
253  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
254  */
255 MLXSW_ITEM64(sp2_afk, block, value, 0x00, 0, MLXSW_SP2_AFK_BITS_PER_BLOCK);
256 
257 /* The key / mask block layout in Spectrum-2 is of the following form:
258  *
259  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
260  * |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |                block11_high                   |
261  * +-----------------------------------------------------------------------------------------------+
262  * |                    block11_low                               |         block10_high           |
263  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
264  * ...
265  */
266 
267 struct mlxsw_sp2_afk_block_layout {
268 	unsigned short offset;
269 	struct mlxsw_item item;
270 };
271 
272 #define MLXSW_SP2_AFK_BLOCK_LAYOUT(_block, _offset, _shift)			\
273 	{									\
274 		.offset = _offset,						\
275 		{								\
276 			.shift = _shift,					\
277 			.size = {.bits = MLXSW_SP2_AFK_BITS_PER_BLOCK},		\
278 			.name = #_block,					\
279 		}								\
280 	}									\
281 
282 static const struct mlxsw_sp2_afk_block_layout mlxsw_sp2_afk_blocks_layout[] = {
283 	MLXSW_SP2_AFK_BLOCK_LAYOUT(block0, 0x30, 0),
284 	MLXSW_SP2_AFK_BLOCK_LAYOUT(block1, 0x2C, 4),
285 	MLXSW_SP2_AFK_BLOCK_LAYOUT(block2, 0x28, 8),
286 	MLXSW_SP2_AFK_BLOCK_LAYOUT(block3, 0x24, 12),
287 	MLXSW_SP2_AFK_BLOCK_LAYOUT(block4, 0x20, 16),
288 	MLXSW_SP2_AFK_BLOCK_LAYOUT(block5, 0x1C, 20),
289 	MLXSW_SP2_AFK_BLOCK_LAYOUT(block6, 0x18, 24),
290 	MLXSW_SP2_AFK_BLOCK_LAYOUT(block7, 0x14, 28),
291 	MLXSW_SP2_AFK_BLOCK_LAYOUT(block8, 0x0C, 0),
292 	MLXSW_SP2_AFK_BLOCK_LAYOUT(block9, 0x08, 4),
293 	MLXSW_SP2_AFK_BLOCK_LAYOUT(block10, 0x04, 8),
294 	MLXSW_SP2_AFK_BLOCK_LAYOUT(block11, 0x00, 12),
295 };
296 
297 static void mlxsw_sp2_afk_encode_block(char *block, int block_index,
298 				       char *output)
299 {
300 	u64 block_value = mlxsw_sp2_afk_block_value_get(block);
301 	const struct mlxsw_sp2_afk_block_layout *block_layout;
302 
303 	if (WARN_ON(block_index < 0 ||
304 		    block_index >= ARRAY_SIZE(mlxsw_sp2_afk_blocks_layout)))
305 		return;
306 
307 	block_layout = &mlxsw_sp2_afk_blocks_layout[block_index];
308 	__mlxsw_item_set64(output + block_layout->offset,
309 			   &block_layout->item, 0, block_value);
310 }
311 
312 const struct mlxsw_afk_ops mlxsw_sp2_afk_ops = {
313 	.blocks		= mlxsw_sp2_afk_blocks,
314 	.blocks_count	= ARRAY_SIZE(mlxsw_sp2_afk_blocks),
315 	.encode_block	= mlxsw_sp2_afk_encode_block,
316 };
317