xref: /openbmc/linux/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c (revision a0ae2562c6c4b2721d9fddba63b7286c13517d9f)
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 static void mlxsw_sp1_afk_encode_u32(const struct mlxsw_item *storage_item,
131 				     const struct mlxsw_item *output_item,
132 				     char *storage, char *output_indexed)
133 {
134 	u32 value;
135 
136 	value = __mlxsw_item_get32(storage, storage_item, 0);
137 	__mlxsw_item_set32(output_indexed, output_item, 0, value);
138 }
139 
140 static void mlxsw_sp1_afk_encode_buf(const struct mlxsw_item *storage_item,
141 				     const struct mlxsw_item *output_item,
142 				     char *storage, char *output_indexed)
143 {
144 	char *storage_data = __mlxsw_item_data(storage, storage_item, 0);
145 	char *output_data = __mlxsw_item_data(output_indexed, output_item, 0);
146 	size_t len = output_item->size.bytes;
147 
148 	memcpy(output_data, storage_data, len);
149 }
150 
151 #define MLXSW_SP1_AFK_KEY_BLOCK_SIZE 16
152 
153 static void
154 mlxsw_sp1_afk_encode_one(const struct mlxsw_afk_element_inst *elinst,
155 			 int block_index, char *storage, char *output)
156 {
157 	unsigned int offset = block_index * MLXSW_SP1_AFK_KEY_BLOCK_SIZE;
158 	char *output_indexed = output + offset;
159 	const struct mlxsw_item *storage_item = &elinst->info->item;
160 	const struct mlxsw_item *output_item = &elinst->item;
161 
162 	if (elinst->type == MLXSW_AFK_ELEMENT_TYPE_U32)
163 		mlxsw_sp1_afk_encode_u32(storage_item, output_item,
164 					 storage, output_indexed);
165 	else if (elinst->type == MLXSW_AFK_ELEMENT_TYPE_BUF)
166 		mlxsw_sp1_afk_encode_buf(storage_item, output_item,
167 					 storage, output_indexed);
168 }
169 
170 const struct mlxsw_afk_ops mlxsw_sp1_afk_ops = {
171 	.blocks		= mlxsw_sp1_afk_blocks,
172 	.blocks_count	= ARRAY_SIZE(mlxsw_sp1_afk_blocks),
173 	.encode_one	= mlxsw_sp1_afk_encode_one,
174 };
175