1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */
3 
4 #include <linux/kernel.h>
5 #include <linux/module.h>
6 #include "spectrum.h"
7 #include "item.h"
8 #include "core_acl_flex_keys.h"
9 
10 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_dmac[] = {
11 	MLXSW_AFK_ELEMENT_INST_BUF(DMAC_32_47, 0x00, 2),
12 	MLXSW_AFK_ELEMENT_INST_BUF(DMAC_0_31, 0x02, 4),
13 	MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x08, 13, 3),
14 	MLXSW_AFK_ELEMENT_INST_U32(VID, 0x08, 0, 12),
15 	MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 8),
16 };
17 
18 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_smac[] = {
19 	MLXSW_AFK_ELEMENT_INST_BUF(SMAC_32_47, 0x00, 2),
20 	MLXSW_AFK_ELEMENT_INST_BUF(SMAC_0_31, 0x02, 4),
21 	MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x08, 13, 3),
22 	MLXSW_AFK_ELEMENT_INST_U32(VID, 0x08, 0, 12),
23 	MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 8),
24 };
25 
26 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l2_smac_ex[] = {
27 	MLXSW_AFK_ELEMENT_INST_BUF(SMAC_32_47, 0x02, 2),
28 	MLXSW_AFK_ELEMENT_INST_BUF(SMAC_0_31, 0x04, 4),
29 	MLXSW_AFK_ELEMENT_INST_U32(ETHERTYPE, 0x0C, 0, 16),
30 };
31 
32 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_sip[] = {
33 	MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x00, 4),
34 	MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x08, 0, 8),
35 	MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 8),
36 };
37 
38 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_dip[] = {
39 	MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_0_31, 0x00, 4),
40 	MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x08, 0, 8),
41 	MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 8),
42 };
43 
44 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4[] = {
45 	MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x00, 4),
46 	MLXSW_AFK_ELEMENT_INST_U32(IP_ECN, 0x04, 4, 2),
47 	MLXSW_AFK_ELEMENT_INST_U32(IP_TTL_, 0x04, 24, 8),
48 	MLXSW_AFK_ELEMENT_INST_U32(IP_DSCP, 0x08, 0, 6),
49 	MLXSW_AFK_ELEMENT_INST_U32(TCP_FLAGS, 0x08, 8, 9), /* TCP_CONTROL+TCP_ECN */
50 };
51 
52 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_ex[] = {
53 	MLXSW_AFK_ELEMENT_INST_U32(VID, 0x00, 0, 12),
54 	MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x08, 29, 3),
55 	MLXSW_AFK_ELEMENT_INST_U32(SRC_L4_PORT, 0x08, 0, 16),
56 	MLXSW_AFK_ELEMENT_INST_U32(DST_L4_PORT, 0x0C, 0, 16),
57 };
58 
59 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_dip[] = {
60 	MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_32_63, 0x00, 4),
61 	MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_0_31, 0x04, 4),
62 };
63 
64 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_ex1[] = {
65 	MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_96_127, 0x00, 4),
66 	MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_64_95, 0x04, 4),
67 	MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x08, 0, 8),
68 };
69 
70 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_sip[] = {
71 	MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_32_63, 0x00, 4),
72 	MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x04, 4),
73 };
74 
75 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_sip_ex[] = {
76 	MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_96_127, 0x00, 4),
77 	MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_64_95, 0x04, 4),
78 };
79 
80 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_packet_type[] = {
81 	MLXSW_AFK_ELEMENT_INST_U32(ETHERTYPE, 0x00, 0, 16),
82 };
83 
84 static const struct mlxsw_afk_block mlxsw_sp1_afk_blocks[] = {
85 	MLXSW_AFK_BLOCK(0x10, mlxsw_sp_afk_element_info_l2_dmac),
86 	MLXSW_AFK_BLOCK(0x11, mlxsw_sp_afk_element_info_l2_smac),
87 	MLXSW_AFK_BLOCK(0x12, mlxsw_sp_afk_element_info_l2_smac_ex),
88 	MLXSW_AFK_BLOCK(0x30, mlxsw_sp_afk_element_info_ipv4_sip),
89 	MLXSW_AFK_BLOCK(0x31, mlxsw_sp_afk_element_info_ipv4_dip),
90 	MLXSW_AFK_BLOCK(0x32, mlxsw_sp_afk_element_info_ipv4),
91 	MLXSW_AFK_BLOCK(0x33, mlxsw_sp_afk_element_info_ipv4_ex),
92 	MLXSW_AFK_BLOCK(0x60, mlxsw_sp_afk_element_info_ipv6_dip),
93 	MLXSW_AFK_BLOCK(0x65, mlxsw_sp_afk_element_info_ipv6_ex1),
94 	MLXSW_AFK_BLOCK(0x62, mlxsw_sp_afk_element_info_ipv6_sip),
95 	MLXSW_AFK_BLOCK(0x63, mlxsw_sp_afk_element_info_ipv6_sip_ex),
96 	MLXSW_AFK_BLOCK(0xB0, mlxsw_sp_afk_element_info_packet_type),
97 };
98 
99 #define MLXSW_SP1_AFK_KEY_BLOCK_SIZE 16
100 
101 static void mlxsw_sp1_afk_encode_block(char *block, int block_index,
102 				       char *output)
103 {
104 	unsigned int offset = block_index * MLXSW_SP1_AFK_KEY_BLOCK_SIZE;
105 	char *output_indexed = output + offset;
106 
107 	memcpy(output_indexed, block, MLXSW_SP1_AFK_KEY_BLOCK_SIZE);
108 }
109 
110 const struct mlxsw_afk_ops mlxsw_sp1_afk_ops = {
111 	.blocks		= mlxsw_sp1_afk_blocks,
112 	.blocks_count	= ARRAY_SIZE(mlxsw_sp1_afk_blocks),
113 	.encode_block	= mlxsw_sp1_afk_encode_block,
114 };
115 
116 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_0[] = {
117 	MLXSW_AFK_ELEMENT_INST_BUF(DMAC_0_31, 0x04, 4),
118 };
119 
120 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_1[] = {
121 	MLXSW_AFK_ELEMENT_INST_BUF(SMAC_0_31, 0x04, 4),
122 };
123 
124 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_2[] = {
125 	MLXSW_AFK_ELEMENT_INST_BUF(SMAC_32_47, 0x04, 2),
126 	MLXSW_AFK_ELEMENT_INST_BUF(DMAC_32_47, 0x06, 2),
127 };
128 
129 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_3[] = {
130 	MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x00, 0, 3),
131 	MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 16, 12),
132 	MLXSW_AFK_ELEMENT_INST_BUF(DMAC_32_47, 0x06, 2),
133 };
134 
135 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_4[] = {
136 	MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x00, 0, 3),
137 	MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 16, 12),
138 	MLXSW_AFK_ELEMENT_INST_U32(ETHERTYPE, 0x04, 0, 16),
139 };
140 
141 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_5[] = {
142 	MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 16, 12),
143 	MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x04, 0, 8), /* RX_ACL_SYSTEM_PORT */
144 };
145 
146 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_0[] = {
147 	MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_0_31, 0x04, 4),
148 };
149 
150 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_1[] = {
151 	MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x04, 4),
152 };
153 
154 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_2[] = {
155 	MLXSW_AFK_ELEMENT_INST_U32(IP_DSCP, 0x04, 0, 6),
156 	MLXSW_AFK_ELEMENT_INST_U32(IP_ECN, 0x04, 6, 2),
157 	MLXSW_AFK_ELEMENT_INST_U32(IP_TTL_, 0x04, 8, 8),
158 	MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x04, 16, 8),
159 };
160 
161 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_0[] = {
162 	MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_32_63, 0x04, 4),
163 };
164 
165 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_1[] = {
166 	MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_64_95, 0x04, 4),
167 };
168 
169 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_2[] = {
170 	MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_96_127, 0x04, 4),
171 };
172 
173 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_3[] = {
174 	MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_32_63, 0x04, 4),
175 };
176 
177 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_4[] = {
178 	MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_64_95, 0x04, 4),
179 };
180 
181 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_5[] = {
182 	MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_96_127, 0x04, 4),
183 };
184 
185 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l4_0[] = {
186 	MLXSW_AFK_ELEMENT_INST_U32(SRC_L4_PORT, 0x04, 16, 16),
187 	MLXSW_AFK_ELEMENT_INST_U32(DST_L4_PORT, 0x04, 0, 16),
188 };
189 
190 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l4_2[] = {
191 	MLXSW_AFK_ELEMENT_INST_U32(TCP_FLAGS, 0x04, 16, 9), /* TCP_CONTROL + TCP_ECN */
192 };
193 
194 static const struct mlxsw_afk_block mlxsw_sp2_afk_blocks[] = {
195 	MLXSW_AFK_BLOCK(0x10, mlxsw_sp_afk_element_info_mac_0),
196 	MLXSW_AFK_BLOCK(0x11, mlxsw_sp_afk_element_info_mac_1),
197 	MLXSW_AFK_BLOCK(0x12, mlxsw_sp_afk_element_info_mac_2),
198 	MLXSW_AFK_BLOCK(0x13, mlxsw_sp_afk_element_info_mac_3),
199 	MLXSW_AFK_BLOCK(0x14, mlxsw_sp_afk_element_info_mac_4),
200 	MLXSW_AFK_BLOCK(0x15, mlxsw_sp_afk_element_info_mac_5),
201 	MLXSW_AFK_BLOCK(0x38, mlxsw_sp_afk_element_info_ipv4_0),
202 	MLXSW_AFK_BLOCK(0x39, mlxsw_sp_afk_element_info_ipv4_1),
203 	MLXSW_AFK_BLOCK(0x3A, mlxsw_sp_afk_element_info_ipv4_2),
204 	MLXSW_AFK_BLOCK(0x40, mlxsw_sp_afk_element_info_ipv6_0),
205 	MLXSW_AFK_BLOCK(0x41, mlxsw_sp_afk_element_info_ipv6_1),
206 	MLXSW_AFK_BLOCK(0x42, mlxsw_sp_afk_element_info_ipv6_2),
207 	MLXSW_AFK_BLOCK(0x43, mlxsw_sp_afk_element_info_ipv6_3),
208 	MLXSW_AFK_BLOCK(0x44, mlxsw_sp_afk_element_info_ipv6_4),
209 	MLXSW_AFK_BLOCK(0x45, mlxsw_sp_afk_element_info_ipv6_5),
210 	MLXSW_AFK_BLOCK(0x90, mlxsw_sp_afk_element_info_l4_0),
211 	MLXSW_AFK_BLOCK(0x92, mlxsw_sp_afk_element_info_l4_2),
212 };
213 
214 #define MLXSW_SP2_AFK_BITS_PER_BLOCK 36
215 
216 /* A block in Spectrum-2 is of the following form:
217  *
218  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
219  * |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |35|34|33|32|
220  * +-----------------------------------------------------------------------------------------------+
221  * |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|
222  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
223  */
224 MLXSW_ITEM64(sp2_afk, block, value, 0x00, 0, MLXSW_SP2_AFK_BITS_PER_BLOCK);
225 
226 /* The key / mask block layout in Spectrum-2 is of the following form:
227  *
228  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
229  * |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |                block11_high                   |
230  * +-----------------------------------------------------------------------------------------------+
231  * |                    block11_low                               |         block10_high           |
232  * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
233  * ...
234  */
235 
236 struct mlxsw_sp2_afk_block_layout {
237 	unsigned short offset;
238 	struct mlxsw_item item;
239 };
240 
241 #define MLXSW_SP2_AFK_BLOCK_LAYOUT(_block, _offset, _shift)			\
242 	{									\
243 		.offset = _offset,						\
244 		{								\
245 			.shift = _shift,					\
246 			.size = {.bits = MLXSW_SP2_AFK_BITS_PER_BLOCK},		\
247 			.name = #_block,					\
248 		}								\
249 	}									\
250 
251 static const struct mlxsw_sp2_afk_block_layout mlxsw_sp2_afk_blocks_layout[] = {
252 	MLXSW_SP2_AFK_BLOCK_LAYOUT(block0, 0x30, 0),
253 	MLXSW_SP2_AFK_BLOCK_LAYOUT(block1, 0x2C, 4),
254 	MLXSW_SP2_AFK_BLOCK_LAYOUT(block2, 0x28, 8),
255 	MLXSW_SP2_AFK_BLOCK_LAYOUT(block3, 0x24, 12),
256 	MLXSW_SP2_AFK_BLOCK_LAYOUT(block4, 0x20, 16),
257 	MLXSW_SP2_AFK_BLOCK_LAYOUT(block5, 0x1C, 20),
258 	MLXSW_SP2_AFK_BLOCK_LAYOUT(block6, 0x18, 24),
259 	MLXSW_SP2_AFK_BLOCK_LAYOUT(block7, 0x14, 28),
260 	MLXSW_SP2_AFK_BLOCK_LAYOUT(block8, 0x0C, 0),
261 	MLXSW_SP2_AFK_BLOCK_LAYOUT(block9, 0x08, 4),
262 	MLXSW_SP2_AFK_BLOCK_LAYOUT(block10, 0x04, 8),
263 	MLXSW_SP2_AFK_BLOCK_LAYOUT(block11, 0x00, 12),
264 };
265 
266 static void mlxsw_sp2_afk_encode_block(char *block, int block_index,
267 				       char *output)
268 {
269 	u64 block_value = mlxsw_sp2_afk_block_value_get(block);
270 	const struct mlxsw_sp2_afk_block_layout *block_layout;
271 
272 	if (WARN_ON(block_index < 0 ||
273 		    block_index >= ARRAY_SIZE(mlxsw_sp2_afk_blocks_layout)))
274 		return;
275 
276 	block_layout = &mlxsw_sp2_afk_blocks_layout[block_index];
277 	__mlxsw_item_set64(output + block_layout->offset,
278 			   &block_layout->item, 0, block_value);
279 }
280 
281 const struct mlxsw_afk_ops mlxsw_sp2_afk_ops = {
282 	.blocks		= mlxsw_sp2_afk_blocks,
283 	.blocks_count	= ARRAY_SIZE(mlxsw_sp2_afk_blocks),
284 	.encode_block	= mlxsw_sp2_afk_encode_block,
285 };
286