1 /* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
2 /* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */
3 
4 #ifndef _MLXSW_CORE_ACL_FLEX_KEYS_H
5 #define _MLXSW_CORE_ACL_FLEX_KEYS_H
6 
7 #include <linux/types.h>
8 #include <linux/bitmap.h>
9 
10 #include "item.h"
11 
12 enum mlxsw_afk_element {
13 	MLXSW_AFK_ELEMENT_SRC_SYS_PORT,
14 	MLXSW_AFK_ELEMENT_DMAC_32_47,
15 	MLXSW_AFK_ELEMENT_DMAC_0_31,
16 	MLXSW_AFK_ELEMENT_SMAC_32_47,
17 	MLXSW_AFK_ELEMENT_SMAC_0_31,
18 	MLXSW_AFK_ELEMENT_ETHERTYPE,
19 	MLXSW_AFK_ELEMENT_IP_PROTO,
20 	MLXSW_AFK_ELEMENT_SRC_IP_96_127,
21 	MLXSW_AFK_ELEMENT_SRC_IP_64_95,
22 	MLXSW_AFK_ELEMENT_SRC_IP_32_63,
23 	MLXSW_AFK_ELEMENT_SRC_IP_0_31,
24 	MLXSW_AFK_ELEMENT_DST_IP_96_127,
25 	MLXSW_AFK_ELEMENT_DST_IP_64_95,
26 	MLXSW_AFK_ELEMENT_DST_IP_32_63,
27 	MLXSW_AFK_ELEMENT_DST_IP_0_31,
28 	MLXSW_AFK_ELEMENT_DST_L4_PORT,
29 	MLXSW_AFK_ELEMENT_SRC_L4_PORT,
30 	MLXSW_AFK_ELEMENT_VID,
31 	MLXSW_AFK_ELEMENT_PCP,
32 	MLXSW_AFK_ELEMENT_TCP_FLAGS,
33 	MLXSW_AFK_ELEMENT_IP_TTL_,
34 	MLXSW_AFK_ELEMENT_IP_ECN,
35 	MLXSW_AFK_ELEMENT_IP_DSCP,
36 	MLXSW_AFK_ELEMENT_VIRT_ROUTER,
37 	MLXSW_AFK_ELEMENT_FDB_MISS,
38 	MLXSW_AFK_ELEMENT_L4_PORT_RANGE,
39 	MLXSW_AFK_ELEMENT_VIRT_ROUTER_0_3,
40 	MLXSW_AFK_ELEMENT_VIRT_ROUTER_4_7,
41 	MLXSW_AFK_ELEMENT_VIRT_ROUTER_MSB,
42 	MLXSW_AFK_ELEMENT_MAX,
43 };
44 
45 enum mlxsw_afk_element_type {
46 	MLXSW_AFK_ELEMENT_TYPE_U32,
47 	MLXSW_AFK_ELEMENT_TYPE_BUF,
48 };
49 
50 struct mlxsw_afk_element_info {
51 	enum mlxsw_afk_element element; /* element ID */
52 	enum mlxsw_afk_element_type type;
53 	struct mlxsw_item item; /* element geometry in internal storage */
54 };
55 
56 #define MLXSW_AFK_ELEMENT_INFO(_type, _element, _offset, _shift, _size)		\
57 	[MLXSW_AFK_ELEMENT_##_element] = {					\
58 		.element = MLXSW_AFK_ELEMENT_##_element,			\
59 		.type = _type,							\
60 		.item = {							\
61 			.offset = _offset,					\
62 			.shift = _shift,					\
63 			.size = {.bits = _size},				\
64 			.name = #_element,					\
65 		},								\
66 	}
67 
68 #define MLXSW_AFK_ELEMENT_INFO_U32(_element, _offset, _shift, _size)		\
69 	MLXSW_AFK_ELEMENT_INFO(MLXSW_AFK_ELEMENT_TYPE_U32,			\
70 			       _element, _offset, _shift, _size)
71 
72 #define MLXSW_AFK_ELEMENT_INFO_BUF(_element, _offset, _size)			\
73 	MLXSW_AFK_ELEMENT_INFO(MLXSW_AFK_ELEMENT_TYPE_BUF,			\
74 			       _element, _offset, 0, _size)
75 
76 #define MLXSW_AFK_ELEMENT_STORAGE_SIZE 0x44
77 
78 struct mlxsw_afk_element_inst { /* element instance in actual block */
79 	enum mlxsw_afk_element element;
80 	enum mlxsw_afk_element_type type;
81 	struct mlxsw_item item; /* element geometry in block */
82 	int u32_key_diff; /* in case value needs to be adjusted before write
83 			   * this diff is here to handle that
84 			   */
85 	bool avoid_size_check;
86 };
87 
88 #define MLXSW_AFK_ELEMENT_INST(_type, _element, _offset,			\
89 			       _shift, _size, _u32_key_diff, _avoid_size_check)	\
90 	{									\
91 		.element = MLXSW_AFK_ELEMENT_##_element,			\
92 		.type = _type,							\
93 		.item = {							\
94 			.offset = _offset,					\
95 			.shift = _shift,					\
96 			.size = {.bits = _size},				\
97 			.name = #_element,					\
98 		},								\
99 		.u32_key_diff = _u32_key_diff,					\
100 		.avoid_size_check = _avoid_size_check,				\
101 	}
102 
103 #define MLXSW_AFK_ELEMENT_INST_U32(_element, _offset, _shift, _size)		\
104 	MLXSW_AFK_ELEMENT_INST(MLXSW_AFK_ELEMENT_TYPE_U32,			\
105 			       _element, _offset, _shift, _size, 0, false)
106 
107 #define MLXSW_AFK_ELEMENT_INST_EXT_U32(_element, _offset,			\
108 				       _shift, _size, _key_diff,		\
109 				       _avoid_size_check)			\
110 	MLXSW_AFK_ELEMENT_INST(MLXSW_AFK_ELEMENT_TYPE_U32,			\
111 			       _element, _offset, _shift, _size,		\
112 			       _key_diff, _avoid_size_check)
113 
114 #define MLXSW_AFK_ELEMENT_INST_BUF(_element, _offset, _size)			\
115 	MLXSW_AFK_ELEMENT_INST(MLXSW_AFK_ELEMENT_TYPE_BUF,			\
116 			       _element, _offset, 0, _size, 0, false)
117 
118 struct mlxsw_afk_block {
119 	u16 encoding; /* block ID */
120 	struct mlxsw_afk_element_inst *instances;
121 	unsigned int instances_count;
122 	bool high_entropy;
123 };
124 
125 #define MLXSW_AFK_BLOCK(_encoding, _instances)					\
126 	{									\
127 		.encoding = _encoding,						\
128 		.instances = _instances,					\
129 		.instances_count = ARRAY_SIZE(_instances),			\
130 	}
131 
132 #define MLXSW_AFK_BLOCK_HIGH_ENTROPY(_encoding, _instances)			\
133 	{									\
134 		.encoding = _encoding,						\
135 		.instances = _instances,					\
136 		.instances_count = ARRAY_SIZE(_instances),			\
137 		.high_entropy = true,						\
138 	}
139 
140 struct mlxsw_afk_element_usage {
141 	DECLARE_BITMAP(usage, MLXSW_AFK_ELEMENT_MAX);
142 };
143 
144 #define mlxsw_afk_element_usage_for_each(element, elusage)			\
145 	for_each_set_bit(element, (elusage)->usage, MLXSW_AFK_ELEMENT_MAX)
146 
147 static inline void
mlxsw_afk_element_usage_add(struct mlxsw_afk_element_usage * elusage,enum mlxsw_afk_element element)148 mlxsw_afk_element_usage_add(struct mlxsw_afk_element_usage *elusage,
149 			    enum mlxsw_afk_element element)
150 {
151 	__set_bit(element, elusage->usage);
152 }
153 
154 static inline void
mlxsw_afk_element_usage_zero(struct mlxsw_afk_element_usage * elusage)155 mlxsw_afk_element_usage_zero(struct mlxsw_afk_element_usage *elusage)
156 {
157 	bitmap_zero(elusage->usage, MLXSW_AFK_ELEMENT_MAX);
158 }
159 
160 static inline void
mlxsw_afk_element_usage_fill(struct mlxsw_afk_element_usage * elusage,const enum mlxsw_afk_element * elements,unsigned int elements_count)161 mlxsw_afk_element_usage_fill(struct mlxsw_afk_element_usage *elusage,
162 			     const enum mlxsw_afk_element *elements,
163 			     unsigned int elements_count)
164 {
165 	int i;
166 
167 	mlxsw_afk_element_usage_zero(elusage);
168 	for (i = 0; i < elements_count; i++)
169 		mlxsw_afk_element_usage_add(elusage, elements[i]);
170 }
171 
172 static inline bool
mlxsw_afk_element_usage_subset(struct mlxsw_afk_element_usage * elusage_small,struct mlxsw_afk_element_usage * elusage_big)173 mlxsw_afk_element_usage_subset(struct mlxsw_afk_element_usage *elusage_small,
174 			       struct mlxsw_afk_element_usage *elusage_big)
175 {
176 	int i;
177 
178 	for (i = 0; i < MLXSW_AFK_ELEMENT_MAX; i++)
179 		if (test_bit(i, elusage_small->usage) &&
180 		    !test_bit(i, elusage_big->usage))
181 			return false;
182 	return true;
183 }
184 
185 struct mlxsw_afk;
186 
187 struct mlxsw_afk_ops {
188 	const struct mlxsw_afk_block *blocks;
189 	unsigned int blocks_count;
190 	void (*encode_block)(char *output, int block_index, char *block);
191 	void (*clear_block)(char *output, int block_index);
192 };
193 
194 struct mlxsw_afk *mlxsw_afk_create(unsigned int max_blocks,
195 				   const struct mlxsw_afk_ops *ops);
196 void mlxsw_afk_destroy(struct mlxsw_afk *mlxsw_afk);
197 
198 struct mlxsw_afk_key_info;
199 
200 struct mlxsw_afk_key_info *
201 mlxsw_afk_key_info_get(struct mlxsw_afk *mlxsw_afk,
202 		       struct mlxsw_afk_element_usage *elusage);
203 void mlxsw_afk_key_info_put(struct mlxsw_afk_key_info *key_info);
204 bool mlxsw_afk_key_info_subset(struct mlxsw_afk_key_info *key_info,
205 			       struct mlxsw_afk_element_usage *elusage);
206 
207 u16
208 mlxsw_afk_key_info_block_encoding_get(const struct mlxsw_afk_key_info *key_info,
209 				      int block_index);
210 unsigned int
211 mlxsw_afk_key_info_blocks_count_get(const struct mlxsw_afk_key_info *key_info);
212 
213 struct mlxsw_afk_element_values {
214 	struct mlxsw_afk_element_usage elusage;
215 	struct {
216 		char key[MLXSW_AFK_ELEMENT_STORAGE_SIZE];
217 		char mask[MLXSW_AFK_ELEMENT_STORAGE_SIZE];
218 	} storage;
219 };
220 
221 void mlxsw_afk_values_add_u32(struct mlxsw_afk_element_values *values,
222 			      enum mlxsw_afk_element element,
223 			      u32 key_value, u32 mask_value);
224 void mlxsw_afk_values_add_buf(struct mlxsw_afk_element_values *values,
225 			      enum mlxsw_afk_element element,
226 			      const char *key_value, const char *mask_value,
227 			      unsigned int len);
228 void mlxsw_afk_encode(struct mlxsw_afk *mlxsw_afk,
229 		      struct mlxsw_afk_key_info *key_info,
230 		      struct mlxsw_afk_element_values *values,
231 		      char *key, char *mask);
232 void mlxsw_afk_clear(struct mlxsw_afk *mlxsw_afk, char *key,
233 		     int block_start, int block_end);
234 
235 #endif
236