1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */
4 #include <linux/kernel.h>
5 #include <linux/module.h>
8 #include "core_acl_flex_keys.h"
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, 16),
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, 16),
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),
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(L4_PORT_RANGE, 0x04, 16, 16),
35 MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x08, 0, 8),
36 MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 16),
39 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_dip[] = {
40 MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_0_31, 0x00, 4),
41 MLXSW_AFK_ELEMENT_INST_U32(L4_PORT_RANGE, 0x04, 16, 16),
42 MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x08, 0, 8),
43 MLXSW_AFK_ELEMENT_INST_U32(SRC_SYS_PORT, 0x0C, 0, 16),
46 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4[] = {
47 MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x00, 4),
48 MLXSW_AFK_ELEMENT_INST_U32(IP_ECN, 0x04, 4, 2),
49 MLXSW_AFK_ELEMENT_INST_U32(IP_TTL_, 0x04, 24, 8),
50 MLXSW_AFK_ELEMENT_INST_U32(IP_DSCP, 0x08, 0, 6),
51 MLXSW_AFK_ELEMENT_INST_U32(TCP_FLAGS, 0x08, 8, 9), /* TCP_CONTROL+TCP_ECN */
54 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_ex[] = {
55 MLXSW_AFK_ELEMENT_INST_U32(VID, 0x00, 0, 12),
56 MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x08, 29, 3),
57 MLXSW_AFK_ELEMENT_INST_U32(SRC_L4_PORT, 0x08, 0, 16),
58 MLXSW_AFK_ELEMENT_INST_U32(DST_L4_PORT, 0x0C, 0, 16),
61 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_dip[] = {
62 MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_32_63, 0x00, 4),
63 MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_0_31, 0x04, 4),
66 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_ex1[] = {
67 MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_96_127, 0x00, 4),
68 MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_64_95, 0x04, 4),
69 MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x08, 0, 8),
72 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_sip[] = {
73 MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_32_63, 0x00, 4),
74 MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x04, 4),
77 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_sip_ex[] = {
78 MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_96_127, 0x00, 4),
79 MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_64_95, 0x04, 4),
82 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_packet_type[] = {
83 MLXSW_AFK_ELEMENT_INST_U32(ETHERTYPE, 0x00, 0, 16),
86 static const struct mlxsw_afk_block mlxsw_sp1_afk_blocks[] = {
87 MLXSW_AFK_BLOCK(0x10, mlxsw_sp_afk_element_info_l2_dmac),
88 MLXSW_AFK_BLOCK(0x11, mlxsw_sp_afk_element_info_l2_smac),
89 MLXSW_AFK_BLOCK(0x12, mlxsw_sp_afk_element_info_l2_smac_ex),
90 MLXSW_AFK_BLOCK(0x30, mlxsw_sp_afk_element_info_ipv4_sip),
91 MLXSW_AFK_BLOCK(0x31, mlxsw_sp_afk_element_info_ipv4_dip),
92 MLXSW_AFK_BLOCK(0x32, mlxsw_sp_afk_element_info_ipv4),
93 MLXSW_AFK_BLOCK(0x33, mlxsw_sp_afk_element_info_ipv4_ex),
94 MLXSW_AFK_BLOCK(0x60, mlxsw_sp_afk_element_info_ipv6_dip),
95 MLXSW_AFK_BLOCK(0x65, mlxsw_sp_afk_element_info_ipv6_ex1),
96 MLXSW_AFK_BLOCK(0x62, mlxsw_sp_afk_element_info_ipv6_sip),
97 MLXSW_AFK_BLOCK(0x63, mlxsw_sp_afk_element_info_ipv6_sip_ex),
98 MLXSW_AFK_BLOCK(0xB0, mlxsw_sp_afk_element_info_packet_type),
101 #define MLXSW_SP1_AFK_KEY_BLOCK_SIZE 16
103 static void mlxsw_sp1_afk_encode_block(char *output, int block_index,
106 unsigned int offset = block_index * MLXSW_SP1_AFK_KEY_BLOCK_SIZE;
107 char *output_indexed = output + offset;
109 memcpy(output_indexed, block, MLXSW_SP1_AFK_KEY_BLOCK_SIZE);
112 static void mlxsw_sp1_afk_clear_block(char *output, int block_index)
114 unsigned int offset = block_index * MLXSW_SP1_AFK_KEY_BLOCK_SIZE;
115 char *output_indexed = output + offset;
117 memset(output_indexed, 0, MLXSW_SP1_AFK_KEY_BLOCK_SIZE);
120 const struct mlxsw_afk_ops mlxsw_sp1_afk_ops = {
121 .blocks = mlxsw_sp1_afk_blocks,
122 .blocks_count = ARRAY_SIZE(mlxsw_sp1_afk_blocks),
123 .encode_block = mlxsw_sp1_afk_encode_block,
124 .clear_block = mlxsw_sp1_afk_clear_block,
127 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_0[] = {
128 MLXSW_AFK_ELEMENT_INST_U32(FDB_MISS, 0x00, 3, 1),
129 MLXSW_AFK_ELEMENT_INST_BUF(DMAC_0_31, 0x04, 4),
132 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_1[] = {
133 MLXSW_AFK_ELEMENT_INST_U32(FDB_MISS, 0x00, 3, 1),
134 MLXSW_AFK_ELEMENT_INST_BUF(SMAC_0_31, 0x04, 4),
137 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_2[] = {
138 MLXSW_AFK_ELEMENT_INST_BUF(SMAC_32_47, 0x04, 2),
139 MLXSW_AFK_ELEMENT_INST_BUF(DMAC_32_47, 0x06, 2),
142 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_3[] = {
143 MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x00, 0, 3),
144 MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 16, 12),
145 MLXSW_AFK_ELEMENT_INST_BUF(DMAC_32_47, 0x06, 2),
148 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_4[] = {
149 MLXSW_AFK_ELEMENT_INST_U32(PCP, 0x00, 0, 3),
150 MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 16, 12),
151 MLXSW_AFK_ELEMENT_INST_U32(ETHERTYPE, 0x04, 0, 16),
154 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_5[] = {
155 MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 16, 12),
156 MLXSW_AFK_ELEMENT_INST_EXT_U32(SRC_SYS_PORT, 0x04, 0, 8, -1, true), /* RX_ACL_SYSTEM_PORT */
159 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_0[] = {
160 MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_0_31, 0x04, 4),
163 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_1[] = {
164 MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x04, 4),
167 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_2[] = {
168 MLXSW_AFK_ELEMENT_INST_U32(IP_DSCP, 0x04, 0, 6),
169 MLXSW_AFK_ELEMENT_INST_U32(IP_ECN, 0x04, 6, 2),
170 MLXSW_AFK_ELEMENT_INST_U32(IP_TTL_, 0x04, 8, 8),
171 MLXSW_AFK_ELEMENT_INST_U32(IP_PROTO, 0x04, 16, 8),
174 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_5[] = {
175 MLXSW_AFK_ELEMENT_INST_EXT_U32(VIRT_ROUTER, 0x04, 20, 11, 0, true),
178 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_0[] = {
179 MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_0_3, 0x00, 0, 4),
180 MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_32_63, 0x04, 4),
183 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_1[] = {
184 MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_4_7, 0x00, 0, 4),
185 MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_64_95, 0x04, 4),
188 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_2[] = {
189 MLXSW_AFK_ELEMENT_INST_EXT_U32(VIRT_ROUTER_MSB, 0x00, 0, 3, 0, true),
190 MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_96_127, 0x04, 4),
193 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_3[] = {
194 MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_32_63, 0x04, 4),
197 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_4[] = {
198 MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_64_95, 0x04, 4),
201 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_5[] = {
202 MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_96_127, 0x04, 4),
205 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l4_0[] = {
206 MLXSW_AFK_ELEMENT_INST_U32(SRC_L4_PORT, 0x04, 16, 16),
207 MLXSW_AFK_ELEMENT_INST_U32(DST_L4_PORT, 0x04, 0, 16),
210 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_l4_2[] = {
211 MLXSW_AFK_ELEMENT_INST_U32(TCP_FLAGS, 0x04, 16, 9), /* TCP_CONTROL + TCP_ECN */
212 MLXSW_AFK_ELEMENT_INST_U32(L4_PORT_RANGE, 0x04, 0, 16),
215 static const struct mlxsw_afk_block mlxsw_sp2_afk_blocks[] = {
216 MLXSW_AFK_BLOCK(0x10, mlxsw_sp_afk_element_info_mac_0),
217 MLXSW_AFK_BLOCK(0x11, mlxsw_sp_afk_element_info_mac_1),
218 MLXSW_AFK_BLOCK(0x12, mlxsw_sp_afk_element_info_mac_2),
219 MLXSW_AFK_BLOCK(0x13, mlxsw_sp_afk_element_info_mac_3),
220 MLXSW_AFK_BLOCK(0x14, mlxsw_sp_afk_element_info_mac_4),
221 MLXSW_AFK_BLOCK(0x15, mlxsw_sp_afk_element_info_mac_5),
222 MLXSW_AFK_BLOCK(0x38, mlxsw_sp_afk_element_info_ipv4_0),
223 MLXSW_AFK_BLOCK(0x39, mlxsw_sp_afk_element_info_ipv4_1),
224 MLXSW_AFK_BLOCK(0x3A, mlxsw_sp_afk_element_info_ipv4_2),
225 MLXSW_AFK_BLOCK(0x3D, mlxsw_sp_afk_element_info_ipv4_5),
226 MLXSW_AFK_BLOCK(0x40, mlxsw_sp_afk_element_info_ipv6_0),
227 MLXSW_AFK_BLOCK(0x41, mlxsw_sp_afk_element_info_ipv6_1),
228 MLXSW_AFK_BLOCK(0x42, mlxsw_sp_afk_element_info_ipv6_2),
229 MLXSW_AFK_BLOCK(0x43, mlxsw_sp_afk_element_info_ipv6_3),
230 MLXSW_AFK_BLOCK(0x44, mlxsw_sp_afk_element_info_ipv6_4),
231 MLXSW_AFK_BLOCK(0x45, mlxsw_sp_afk_element_info_ipv6_5),
232 MLXSW_AFK_BLOCK(0x90, mlxsw_sp_afk_element_info_l4_0),
233 MLXSW_AFK_BLOCK(0x92, mlxsw_sp_afk_element_info_l4_2),
236 #define MLXSW_SP2_AFK_BITS_PER_BLOCK 36
238 /* A block in Spectrum-2 is of the following form:
240 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
241 * | | | | | | | | | | | | | | | | | | | | | | | | | | | | |35|34|33|32|
242 * +-----------------------------------------------------------------------------------------------+
243 * |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|
244 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
246 MLXSW_ITEM64(sp2_afk, block, value, 0x00, 0, MLXSW_SP2_AFK_BITS_PER_BLOCK);
248 /* The key / mask block layout in Spectrum-2 is of the following form:
250 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
251 * | | | | | | | | | | | | | | | | | block11_high |
252 * +-----------------------------------------------------------------------------------------------+
253 * | block11_low | block10_high |
254 * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
258 struct mlxsw_sp2_afk_block_layout {
259 unsigned short offset;
260 struct mlxsw_item item;
263 #define MLXSW_SP2_AFK_BLOCK_LAYOUT(_block, _offset, _shift) \
268 .size = {.bits = MLXSW_SP2_AFK_BITS_PER_BLOCK}, \
273 static const struct mlxsw_sp2_afk_block_layout mlxsw_sp2_afk_blocks_layout[] = {
274 MLXSW_SP2_AFK_BLOCK_LAYOUT(block0, 0x30, 0),
275 MLXSW_SP2_AFK_BLOCK_LAYOUT(block1, 0x2C, 4),
276 MLXSW_SP2_AFK_BLOCK_LAYOUT(block2, 0x28, 8),
277 MLXSW_SP2_AFK_BLOCK_LAYOUT(block3, 0x24, 12),
278 MLXSW_SP2_AFK_BLOCK_LAYOUT(block4, 0x20, 16),
279 MLXSW_SP2_AFK_BLOCK_LAYOUT(block5, 0x1C, 20),
280 MLXSW_SP2_AFK_BLOCK_LAYOUT(block6, 0x18, 24),
281 MLXSW_SP2_AFK_BLOCK_LAYOUT(block7, 0x14, 28),
282 MLXSW_SP2_AFK_BLOCK_LAYOUT(block8, 0x0C, 0),
283 MLXSW_SP2_AFK_BLOCK_LAYOUT(block9, 0x08, 4),
284 MLXSW_SP2_AFK_BLOCK_LAYOUT(block10, 0x04, 8),
285 MLXSW_SP2_AFK_BLOCK_LAYOUT(block11, 0x00, 12),
288 static void __mlxsw_sp2_afk_block_value_set(char *output, int block_index,
291 const struct mlxsw_sp2_afk_block_layout *block_layout;
293 if (WARN_ON(block_index < 0 ||
294 block_index >= ARRAY_SIZE(mlxsw_sp2_afk_blocks_layout)))
297 block_layout = &mlxsw_sp2_afk_blocks_layout[block_index];
298 __mlxsw_item_set64(output + block_layout->offset,
299 &block_layout->item, 0, block_value);
302 static void mlxsw_sp2_afk_encode_block(char *output, int block_index,
305 u64 block_value = mlxsw_sp2_afk_block_value_get(block);
307 __mlxsw_sp2_afk_block_value_set(output, block_index, block_value);
310 static void mlxsw_sp2_afk_clear_block(char *output, int block_index)
312 __mlxsw_sp2_afk_block_value_set(output, block_index, 0);
315 const struct mlxsw_afk_ops mlxsw_sp2_afk_ops = {
316 .blocks = mlxsw_sp2_afk_blocks,
317 .blocks_count = ARRAY_SIZE(mlxsw_sp2_afk_blocks),
318 .encode_block = mlxsw_sp2_afk_encode_block,
319 .clear_block = mlxsw_sp2_afk_clear_block,
322 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_5b[] = {
323 MLXSW_AFK_ELEMENT_INST_U32(VID, 0x04, 18, 12),
324 MLXSW_AFK_ELEMENT_INST_EXT_U32(SRC_SYS_PORT, 0x04, 0, 9, -1, true), /* RX_ACL_SYSTEM_PORT */
327 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_5b[] = {
328 MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER, 0x04, 20, 12),
331 static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv6_2b[] = {
332 MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER_MSB, 0x00, 0, 4),
333 MLXSW_AFK_ELEMENT_INST_BUF(DST_IP_96_127, 0x04, 4),
336 static const struct mlxsw_afk_block mlxsw_sp4_afk_blocks[] = {
337 MLXSW_AFK_BLOCK_HIGH_ENTROPY(0x10, mlxsw_sp_afk_element_info_mac_0),
338 MLXSW_AFK_BLOCK_HIGH_ENTROPY(0x11, mlxsw_sp_afk_element_info_mac_1),
339 MLXSW_AFK_BLOCK(0x12, mlxsw_sp_afk_element_info_mac_2),
340 MLXSW_AFK_BLOCK(0x13, mlxsw_sp_afk_element_info_mac_3),
341 MLXSW_AFK_BLOCK(0x14, mlxsw_sp_afk_element_info_mac_4),
342 MLXSW_AFK_BLOCK_HIGH_ENTROPY(0x1A, mlxsw_sp_afk_element_info_mac_5b),
343 MLXSW_AFK_BLOCK_HIGH_ENTROPY(0x38, mlxsw_sp_afk_element_info_ipv4_0),
344 MLXSW_AFK_BLOCK_HIGH_ENTROPY(0x39, mlxsw_sp_afk_element_info_ipv4_1),
345 MLXSW_AFK_BLOCK(0x3A, mlxsw_sp_afk_element_info_ipv4_2),
346 MLXSW_AFK_BLOCK(0x36, mlxsw_sp_afk_element_info_ipv4_5b),
347 MLXSW_AFK_BLOCK(0x40, mlxsw_sp_afk_element_info_ipv6_0),
348 MLXSW_AFK_BLOCK(0x41, mlxsw_sp_afk_element_info_ipv6_1),
349 MLXSW_AFK_BLOCK(0x47, mlxsw_sp_afk_element_info_ipv6_2b),
350 MLXSW_AFK_BLOCK(0x43, mlxsw_sp_afk_element_info_ipv6_3),
351 MLXSW_AFK_BLOCK(0x44, mlxsw_sp_afk_element_info_ipv6_4),
352 MLXSW_AFK_BLOCK(0x45, mlxsw_sp_afk_element_info_ipv6_5),
353 MLXSW_AFK_BLOCK_HIGH_ENTROPY(0x90, mlxsw_sp_afk_element_info_l4_0),
354 MLXSW_AFK_BLOCK(0x92, mlxsw_sp_afk_element_info_l4_2),
357 const struct mlxsw_afk_ops mlxsw_sp4_afk_ops = {
358 .blocks = mlxsw_sp4_afk_blocks,
359 .blocks_count = ARRAY_SIZE(mlxsw_sp4_afk_blocks),
360 .encode_block = mlxsw_sp2_afk_encode_block,
361 .clear_block = mlxsw_sp2_afk_clear_block,