1 /*
2  * drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h
3  * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
4  * Copyright (c) 2017 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 #ifndef _MLXSW_CORE_ACL_FLEX_KEYS_H
36 #define _MLXSW_CORE_ACL_FLEX_KEYS_H
37 
38 #include <linux/types.h>
39 #include <linux/bitmap.h>
40 
41 #include "item.h"
42 
43 enum mlxsw_afk_element {
44 	MLXSW_AFK_ELEMENT_SRC_SYS_PORT,
45 	MLXSW_AFK_ELEMENT_DMAC,
46 	MLXSW_AFK_ELEMENT_SMAC,
47 	MLXSW_AFK_ELEMENT_ETHERTYPE,
48 	MLXSW_AFK_ELEMENT_IP_PROTO,
49 	MLXSW_AFK_ELEMENT_SRC_IP4,
50 	MLXSW_AFK_ELEMENT_DST_IP4,
51 	MLXSW_AFK_ELEMENT_SRC_IP6_HI,
52 	MLXSW_AFK_ELEMENT_SRC_IP6_LO,
53 	MLXSW_AFK_ELEMENT_DST_IP6_HI,
54 	MLXSW_AFK_ELEMENT_DST_IP6_LO,
55 	MLXSW_AFK_ELEMENT_DST_L4_PORT,
56 	MLXSW_AFK_ELEMENT_SRC_L4_PORT,
57 	MLXSW_AFK_ELEMENT_VID,
58 	MLXSW_AFK_ELEMENT_PCP,
59 	MLXSW_AFK_ELEMENT_TCP_FLAGS,
60 	MLXSW_AFK_ELEMENT_IP_TTL_,
61 	MLXSW_AFK_ELEMENT_MAX,
62 };
63 
64 enum mlxsw_afk_element_type {
65 	MLXSW_AFK_ELEMENT_TYPE_U32,
66 	MLXSW_AFK_ELEMENT_TYPE_BUF,
67 };
68 
69 struct mlxsw_afk_element_info {
70 	enum mlxsw_afk_element element; /* element ID */
71 	enum mlxsw_afk_element_type type;
72 	struct mlxsw_item item; /* element geometry in internal storage */
73 };
74 
75 #define MLXSW_AFK_ELEMENT_INFO(_type, _element, _offset, _shift, _size)		\
76 	[MLXSW_AFK_ELEMENT_##_element] = {					\
77 		.element = MLXSW_AFK_ELEMENT_##_element,			\
78 		.type = _type,							\
79 		.item = {							\
80 			.offset = _offset,					\
81 			.shift = _shift,					\
82 			.size = {.bits = _size},				\
83 			.name = #_element,					\
84 		},								\
85 	}
86 
87 #define MLXSW_AFK_ELEMENT_INFO_U32(_element, _offset, _shift, _size)		\
88 	MLXSW_AFK_ELEMENT_INFO(MLXSW_AFK_ELEMENT_TYPE_U32,			\
89 			       _element, _offset, _shift, _size)
90 
91 #define MLXSW_AFK_ELEMENT_INFO_BUF(_element, _offset, _size)			\
92 	MLXSW_AFK_ELEMENT_INFO(MLXSW_AFK_ELEMENT_TYPE_BUF,			\
93 			       _element, _offset, 0, _size)
94 
95 /* For the purpose of the driver, define an internal storage scratchpad
96  * that will be used to store key/mask values. For each defined element type
97  * define an internal storage geometry.
98  */
99 static const struct mlxsw_afk_element_info mlxsw_afk_element_infos[] = {
100 	MLXSW_AFK_ELEMENT_INFO_U32(SRC_SYS_PORT, 0x00, 16, 16),
101 	MLXSW_AFK_ELEMENT_INFO_BUF(DMAC, 0x04, 6),
102 	MLXSW_AFK_ELEMENT_INFO_BUF(SMAC, 0x0A, 6),
103 	MLXSW_AFK_ELEMENT_INFO_U32(ETHERTYPE, 0x00, 0, 16),
104 	MLXSW_AFK_ELEMENT_INFO_U32(IP_PROTO, 0x10, 0, 8),
105 	MLXSW_AFK_ELEMENT_INFO_U32(VID, 0x10, 8, 12),
106 	MLXSW_AFK_ELEMENT_INFO_U32(PCP, 0x10, 20, 3),
107 	MLXSW_AFK_ELEMENT_INFO_U32(TCP_FLAGS, 0x10, 23, 9),
108 	MLXSW_AFK_ELEMENT_INFO_U32(IP_TTL_, 0x14, 0, 8),
109 	MLXSW_AFK_ELEMENT_INFO_U32(SRC_IP4, 0x18, 0, 32),
110 	MLXSW_AFK_ELEMENT_INFO_U32(DST_IP4, 0x1C, 0, 32),
111 	MLXSW_AFK_ELEMENT_INFO_BUF(SRC_IP6_HI, 0x18, 8),
112 	MLXSW_AFK_ELEMENT_INFO_BUF(SRC_IP6_LO, 0x20, 8),
113 	MLXSW_AFK_ELEMENT_INFO_BUF(DST_IP6_HI, 0x28, 8),
114 	MLXSW_AFK_ELEMENT_INFO_BUF(DST_IP6_LO, 0x30, 8),
115 	MLXSW_AFK_ELEMENT_INFO_U32(DST_L4_PORT, 0x14, 0, 16),
116 	MLXSW_AFK_ELEMENT_INFO_U32(SRC_L4_PORT, 0x14, 16, 16),
117 };
118 
119 #define MLXSW_AFK_ELEMENT_STORAGE_SIZE 0x38
120 
121 struct mlxsw_afk_element_inst { /* element instance in actual block */
122 	const struct mlxsw_afk_element_info *info;
123 	enum mlxsw_afk_element_type type;
124 	struct mlxsw_item item; /* element geometry in block */
125 };
126 
127 #define MLXSW_AFK_ELEMENT_INST(_type, _element, _offset, _shift, _size)		\
128 	{									\
129 		.info = &mlxsw_afk_element_infos[MLXSW_AFK_ELEMENT_##_element],	\
130 		.type = _type,							\
131 		.item = {							\
132 			.offset = _offset,					\
133 			.shift = _shift,					\
134 			.size = {.bits = _size},				\
135 			.name = #_element,					\
136 		},								\
137 	}
138 
139 #define MLXSW_AFK_ELEMENT_INST_U32(_element, _offset, _shift, _size)		\
140 	MLXSW_AFK_ELEMENT_INST(MLXSW_AFK_ELEMENT_TYPE_U32,			\
141 			       _element, _offset, _shift, _size)
142 
143 #define MLXSW_AFK_ELEMENT_INST_BUF(_element, _offset, _size)			\
144 	MLXSW_AFK_ELEMENT_INST(MLXSW_AFK_ELEMENT_TYPE_BUF,			\
145 			       _element, _offset, 0, _size)
146 
147 struct mlxsw_afk_block {
148 	u16 encoding; /* block ID */
149 	struct mlxsw_afk_element_inst *instances;
150 	unsigned int instances_count;
151 };
152 
153 #define MLXSW_AFK_BLOCK(_encoding, _instances)					\
154 	{									\
155 		.encoding = _encoding,						\
156 		.instances = _instances,					\
157 		.instances_count = ARRAY_SIZE(_instances),			\
158 	}
159 
160 struct mlxsw_afk_element_usage {
161 	DECLARE_BITMAP(usage, MLXSW_AFK_ELEMENT_MAX);
162 };
163 
164 #define mlxsw_afk_element_usage_for_each(element, elusage)			\
165 	for_each_set_bit(element, (elusage)->usage, MLXSW_AFK_ELEMENT_MAX)
166 
167 static inline void
168 mlxsw_afk_element_usage_add(struct mlxsw_afk_element_usage *elusage,
169 			    enum mlxsw_afk_element element)
170 {
171 	__set_bit(element, elusage->usage);
172 }
173 
174 static inline void
175 mlxsw_afk_element_usage_zero(struct mlxsw_afk_element_usage *elusage)
176 {
177 	bitmap_zero(elusage->usage, MLXSW_AFK_ELEMENT_MAX);
178 }
179 
180 static inline void
181 mlxsw_afk_element_usage_fill(struct mlxsw_afk_element_usage *elusage,
182 			     const enum mlxsw_afk_element *elements,
183 			     unsigned int elements_count)
184 {
185 	int i;
186 
187 	mlxsw_afk_element_usage_zero(elusage);
188 	for (i = 0; i < elements_count; i++)
189 		mlxsw_afk_element_usage_add(elusage, elements[i]);
190 }
191 
192 static inline bool
193 mlxsw_afk_element_usage_subset(struct mlxsw_afk_element_usage *elusage_small,
194 			       struct mlxsw_afk_element_usage *elusage_big)
195 {
196 	int i;
197 
198 	for (i = 0; i < MLXSW_AFK_ELEMENT_MAX; i++)
199 		if (test_bit(i, elusage_small->usage) &&
200 		    !test_bit(i, elusage_big->usage))
201 			return false;
202 	return true;
203 }
204 
205 struct mlxsw_afk;
206 
207 struct mlxsw_afk *mlxsw_afk_create(unsigned int max_blocks,
208 				   const struct mlxsw_afk_block *blocks,
209 				   unsigned int blocks_count);
210 void mlxsw_afk_destroy(struct mlxsw_afk *mlxsw_afk);
211 
212 struct mlxsw_afk_key_info;
213 
214 struct mlxsw_afk_key_info *
215 mlxsw_afk_key_info_get(struct mlxsw_afk *mlxsw_afk,
216 		       struct mlxsw_afk_element_usage *elusage);
217 void mlxsw_afk_key_info_put(struct mlxsw_afk_key_info *key_info);
218 bool mlxsw_afk_key_info_subset(struct mlxsw_afk_key_info *key_info,
219 			       struct mlxsw_afk_element_usage *elusage);
220 
221 u16
222 mlxsw_afk_key_info_block_encoding_get(const struct mlxsw_afk_key_info *key_info,
223 				      int block_index);
224 unsigned int
225 mlxsw_afk_key_info_blocks_count_get(const struct mlxsw_afk_key_info *key_info);
226 
227 struct mlxsw_afk_element_values {
228 	struct mlxsw_afk_element_usage elusage;
229 	struct {
230 		char key[MLXSW_AFK_ELEMENT_STORAGE_SIZE];
231 		char mask[MLXSW_AFK_ELEMENT_STORAGE_SIZE];
232 	} storage;
233 };
234 
235 void mlxsw_afk_values_add_u32(struct mlxsw_afk_element_values *values,
236 			      enum mlxsw_afk_element element,
237 			      u32 key_value, u32 mask_value);
238 void mlxsw_afk_values_add_buf(struct mlxsw_afk_element_values *values,
239 			      enum mlxsw_afk_element element,
240 			      const char *key_value, const char *mask_value,
241 			      unsigned int len);
242 void mlxsw_afk_encode(struct mlxsw_afk_key_info *key_info,
243 		      struct mlxsw_afk_element_values *values,
244 		      char *key, char *mask);
245 
246 #endif
247