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_SPECTRUM_ACL_TCAM_H
5 #define _MLXSW_SPECTRUM_ACL_TCAM_H
6 
7 #include <linux/list.h>
8 #include <linux/parman.h>
9 
10 #include "reg.h"
11 #include "spectrum.h"
12 #include "core_acl_flex_keys.h"
13 
14 struct mlxsw_sp_acl_tcam {
15 	unsigned long *used_regions; /* bit array */
16 	unsigned int max_regions;
17 	unsigned long *used_groups;  /* bit array */
18 	unsigned int max_groups;
19 	unsigned int max_group_size;
20 	unsigned long priv[0];
21 	/* priv has to be always the last item */
22 };
23 
24 size_t mlxsw_sp_acl_tcam_priv_size(struct mlxsw_sp *mlxsw_sp);
25 int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,
26 			   struct mlxsw_sp_acl_tcam *tcam);
27 void mlxsw_sp_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp,
28 			    struct mlxsw_sp_acl_tcam *tcam);
29 int mlxsw_sp_acl_tcam_priority_get(struct mlxsw_sp *mlxsw_sp,
30 				   struct mlxsw_sp_acl_rule_info *rulei,
31 				   u32 *priority, bool fillup_priority);
32 
33 struct mlxsw_sp_acl_profile_ops {
34 	size_t ruleset_priv_size;
35 	int (*ruleset_add)(struct mlxsw_sp *mlxsw_sp,
36 			   struct mlxsw_sp_acl_tcam *tcam, void *ruleset_priv,
37 			   struct mlxsw_afk_element_usage *tmplt_elusage);
38 	void (*ruleset_del)(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv);
39 	int (*ruleset_bind)(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv,
40 			    struct mlxsw_sp_port *mlxsw_sp_port,
41 			    bool ingress);
42 	void (*ruleset_unbind)(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv,
43 			       struct mlxsw_sp_port *mlxsw_sp_port,
44 			       bool ingress);
45 	u16 (*ruleset_group_id)(void *ruleset_priv);
46 	size_t (*rule_priv_size)(struct mlxsw_sp *mlxsw_sp);
47 	int (*rule_add)(struct mlxsw_sp *mlxsw_sp,
48 			void *ruleset_priv, void *rule_priv,
49 			struct mlxsw_sp_acl_rule_info *rulei);
50 	void (*rule_del)(struct mlxsw_sp *mlxsw_sp, void *rule_priv);
51 	int (*rule_action_replace)(struct mlxsw_sp *mlxsw_sp,
52 				   void *ruleset_priv, void *rule_priv,
53 				   struct mlxsw_sp_acl_rule_info *rulei);
54 	int (*rule_activity_get)(struct mlxsw_sp *mlxsw_sp, void *rule_priv,
55 				 bool *activity);
56 };
57 
58 const struct mlxsw_sp_acl_profile_ops *
59 mlxsw_sp_acl_tcam_profile_ops(struct mlxsw_sp *mlxsw_sp,
60 			      enum mlxsw_sp_acl_profile profile);
61 
62 #define MLXSW_SP_ACL_TCAM_REGION_BASE_COUNT 16
63 #define MLXSW_SP_ACL_TCAM_REGION_RESIZE_STEP 16
64 
65 #define MLXSW_SP_ACL_TCAM_CATCHALL_PRIO (~0U)
66 
67 #define MLXSW_SP_ACL_TCAM_MASK_LEN \
68 	(MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN * BITS_PER_BYTE)
69 
70 struct mlxsw_sp_acl_tcam_group;
71 
72 struct mlxsw_sp_acl_tcam_region {
73 	struct list_head list; /* Member of a TCAM group */
74 	struct list_head chunk_list; /* List of chunks under this region */
75 	struct mlxsw_sp_acl_tcam_group *group;
76 	enum mlxsw_reg_ptar_key_type key_type;
77 	u16 id; /* ACL ID and region ID - they are same */
78 	char tcam_region_info[MLXSW_REG_PXXX_TCAM_REGION_INFO_LEN];
79 	struct mlxsw_afk_key_info *key_info;
80 	struct mlxsw_sp *mlxsw_sp;
81 	unsigned long priv[0];
82 	/* priv has to be always the last item */
83 };
84 
85 struct mlxsw_sp_acl_ctcam_region {
86 	struct parman *parman;
87 	const struct mlxsw_sp_acl_ctcam_region_ops *ops;
88 	struct mlxsw_sp_acl_tcam_region *region;
89 };
90 
91 struct mlxsw_sp_acl_ctcam_chunk {
92 	struct parman_prio parman_prio;
93 };
94 
95 struct mlxsw_sp_acl_ctcam_entry {
96 	struct parman_item parman_item;
97 };
98 
99 struct mlxsw_sp_acl_ctcam_region_ops {
100 	int (*entry_insert)(struct mlxsw_sp_acl_ctcam_region *cregion,
101 			    struct mlxsw_sp_acl_ctcam_entry *centry,
102 			    const char *mask);
103 	void (*entry_remove)(struct mlxsw_sp_acl_ctcam_region *cregion,
104 			     struct mlxsw_sp_acl_ctcam_entry *centry);
105 };
106 
107 int
108 mlxsw_sp_acl_ctcam_region_init(struct mlxsw_sp *mlxsw_sp,
109 			       struct mlxsw_sp_acl_ctcam_region *cregion,
110 			       struct mlxsw_sp_acl_tcam_region *region,
111 			       const struct mlxsw_sp_acl_ctcam_region_ops *ops);
112 void mlxsw_sp_acl_ctcam_region_fini(struct mlxsw_sp_acl_ctcam_region *cregion);
113 void mlxsw_sp_acl_ctcam_chunk_init(struct mlxsw_sp_acl_ctcam_region *cregion,
114 				   struct mlxsw_sp_acl_ctcam_chunk *cchunk,
115 				   unsigned int priority);
116 void mlxsw_sp_acl_ctcam_chunk_fini(struct mlxsw_sp_acl_ctcam_chunk *cchunk);
117 int mlxsw_sp_acl_ctcam_entry_add(struct mlxsw_sp *mlxsw_sp,
118 				 struct mlxsw_sp_acl_ctcam_region *cregion,
119 				 struct mlxsw_sp_acl_ctcam_chunk *cchunk,
120 				 struct mlxsw_sp_acl_ctcam_entry *centry,
121 				 struct mlxsw_sp_acl_rule_info *rulei,
122 				 bool fillup_priority);
123 void mlxsw_sp_acl_ctcam_entry_del(struct mlxsw_sp *mlxsw_sp,
124 				  struct mlxsw_sp_acl_ctcam_region *cregion,
125 				  struct mlxsw_sp_acl_ctcam_chunk *cchunk,
126 				  struct mlxsw_sp_acl_ctcam_entry *centry);
127 int mlxsw_sp_acl_ctcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
128 					    struct mlxsw_sp_acl_ctcam_region *cregion,
129 					    struct mlxsw_sp_acl_ctcam_chunk *cchunk,
130 					    struct mlxsw_sp_acl_ctcam_entry *centry,
131 					    struct mlxsw_sp_acl_rule_info *rulei);
132 static inline unsigned int
133 mlxsw_sp_acl_ctcam_entry_offset(struct mlxsw_sp_acl_ctcam_entry *centry)
134 {
135 	return centry->parman_item.index;
136 }
137 
138 enum mlxsw_sp_acl_atcam_region_type {
139 	MLXSW_SP_ACL_ATCAM_REGION_TYPE_2KB,
140 	MLXSW_SP_ACL_ATCAM_REGION_TYPE_4KB,
141 	MLXSW_SP_ACL_ATCAM_REGION_TYPE_8KB,
142 	MLXSW_SP_ACL_ATCAM_REGION_TYPE_12KB,
143 	__MLXSW_SP_ACL_ATCAM_REGION_TYPE_MAX,
144 };
145 
146 #define MLXSW_SP_ACL_ATCAM_REGION_TYPE_MAX \
147 	(__MLXSW_SP_ACL_ATCAM_REGION_TYPE_MAX - 1)
148 
149 struct mlxsw_sp_acl_atcam {
150 	struct mlxsw_sp_acl_erp_core *erp_core;
151 };
152 
153 struct mlxsw_sp_acl_atcam_region {
154 	struct rhashtable entries_ht; /* A-TCAM only */
155 	struct list_head entries_list; /* A-TCAM only */
156 	struct mlxsw_sp_acl_ctcam_region cregion;
157 	const struct mlxsw_sp_acl_atcam_region_ops *ops;
158 	struct mlxsw_sp_acl_tcam_region *region;
159 	struct mlxsw_sp_acl_atcam *atcam;
160 	enum mlxsw_sp_acl_atcam_region_type type;
161 	struct mlxsw_sp_acl_erp_table *erp_table;
162 	void *priv;
163 };
164 
165 struct mlxsw_sp_acl_atcam_entry_ht_key {
166 	char enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded key,
167 							    * minus delta bits.
168 							    */
169 	u8 erp_id;
170 };
171 
172 struct mlxsw_sp_acl_atcam_chunk {
173 	struct mlxsw_sp_acl_ctcam_chunk cchunk;
174 };
175 
176 struct mlxsw_sp_acl_atcam_entry {
177 	struct rhash_head ht_node;
178 	struct list_head list; /* Member in entries_list */
179 	struct mlxsw_sp_acl_atcam_entry_ht_key ht_key;
180 	char full_enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded key */
181 	struct {
182 		u16 start;
183 		u8 mask;
184 		u8 value;
185 	} delta_info;
186 	struct mlxsw_sp_acl_ctcam_entry centry;
187 	struct mlxsw_sp_acl_atcam_lkey_id *lkey_id;
188 	struct mlxsw_sp_acl_erp_mask *erp_mask;
189 };
190 
191 static inline struct mlxsw_sp_acl_atcam_region *
192 mlxsw_sp_acl_tcam_cregion_aregion(struct mlxsw_sp_acl_ctcam_region *cregion)
193 {
194 	return container_of(cregion, struct mlxsw_sp_acl_atcam_region, cregion);
195 }
196 
197 static inline struct mlxsw_sp_acl_atcam_entry *
198 mlxsw_sp_acl_tcam_centry_aentry(struct mlxsw_sp_acl_ctcam_entry *centry)
199 {
200 	return container_of(centry, struct mlxsw_sp_acl_atcam_entry, centry);
201 }
202 
203 int mlxsw_sp_acl_atcam_region_associate(struct mlxsw_sp *mlxsw_sp,
204 					u16 region_id);
205 int
206 mlxsw_sp_acl_atcam_region_init(struct mlxsw_sp *mlxsw_sp,
207 			       struct mlxsw_sp_acl_atcam *atcam,
208 			       struct mlxsw_sp_acl_atcam_region *aregion,
209 			       struct mlxsw_sp_acl_tcam_region *region,
210 			       const struct mlxsw_sp_acl_ctcam_region_ops *ops);
211 void mlxsw_sp_acl_atcam_region_fini(struct mlxsw_sp_acl_atcam_region *aregion);
212 void mlxsw_sp_acl_atcam_chunk_init(struct mlxsw_sp_acl_atcam_region *aregion,
213 				   struct mlxsw_sp_acl_atcam_chunk *achunk,
214 				   unsigned int priority);
215 void mlxsw_sp_acl_atcam_chunk_fini(struct mlxsw_sp_acl_atcam_chunk *achunk);
216 int mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp,
217 				 struct mlxsw_sp_acl_atcam_region *aregion,
218 				 struct mlxsw_sp_acl_atcam_chunk *achunk,
219 				 struct mlxsw_sp_acl_atcam_entry *aentry,
220 				 struct mlxsw_sp_acl_rule_info *rulei);
221 void mlxsw_sp_acl_atcam_entry_del(struct mlxsw_sp *mlxsw_sp,
222 				  struct mlxsw_sp_acl_atcam_region *aregion,
223 				  struct mlxsw_sp_acl_atcam_chunk *achunk,
224 				  struct mlxsw_sp_acl_atcam_entry *aentry);
225 int mlxsw_sp_acl_atcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
226 					    struct mlxsw_sp_acl_atcam_region *aregion,
227 					    struct mlxsw_sp_acl_atcam_chunk *achunk,
228 					    struct mlxsw_sp_acl_atcam_entry *aentry,
229 					    struct mlxsw_sp_acl_rule_info *rulei);
230 int mlxsw_sp_acl_atcam_init(struct mlxsw_sp *mlxsw_sp,
231 			    struct mlxsw_sp_acl_atcam *atcam);
232 void mlxsw_sp_acl_atcam_fini(struct mlxsw_sp *mlxsw_sp,
233 			     struct mlxsw_sp_acl_atcam *atcam);
234 
235 struct mlxsw_sp_acl_erp_delta;
236 
237 u16 mlxsw_sp_acl_erp_delta_start(const struct mlxsw_sp_acl_erp_delta *delta);
238 u8 mlxsw_sp_acl_erp_delta_mask(const struct mlxsw_sp_acl_erp_delta *delta);
239 u8 mlxsw_sp_acl_erp_delta_value(const struct mlxsw_sp_acl_erp_delta *delta,
240 				const char *enc_key);
241 void mlxsw_sp_acl_erp_delta_clear(const struct mlxsw_sp_acl_erp_delta *delta,
242 				  const char *enc_key);
243 
244 struct mlxsw_sp_acl_erp_mask;
245 
246 bool
247 mlxsw_sp_acl_erp_mask_is_ctcam(const struct mlxsw_sp_acl_erp_mask *erp_mask);
248 u8 mlxsw_sp_acl_erp_mask_erp_id(const struct mlxsw_sp_acl_erp_mask *erp_mask);
249 const struct mlxsw_sp_acl_erp_delta *
250 mlxsw_sp_acl_erp_delta(const struct mlxsw_sp_acl_erp_mask *erp_mask);
251 struct mlxsw_sp_acl_erp_mask *
252 mlxsw_sp_acl_erp_mask_get(struct mlxsw_sp_acl_atcam_region *aregion,
253 			  const char *mask, bool ctcam);
254 void mlxsw_sp_acl_erp_mask_put(struct mlxsw_sp_acl_atcam_region *aregion,
255 			       struct mlxsw_sp_acl_erp_mask *erp_mask);
256 int mlxsw_sp_acl_erp_bf_insert(struct mlxsw_sp *mlxsw_sp,
257 			       struct mlxsw_sp_acl_atcam_region *aregion,
258 			       struct mlxsw_sp_acl_erp_mask *erp_mask,
259 			       struct mlxsw_sp_acl_atcam_entry *aentry);
260 void mlxsw_sp_acl_erp_bf_remove(struct mlxsw_sp *mlxsw_sp,
261 				struct mlxsw_sp_acl_atcam_region *aregion,
262 				struct mlxsw_sp_acl_erp_mask *erp_mask,
263 				struct mlxsw_sp_acl_atcam_entry *aentry);
264 int mlxsw_sp_acl_erp_region_init(struct mlxsw_sp_acl_atcam_region *aregion);
265 void mlxsw_sp_acl_erp_region_fini(struct mlxsw_sp_acl_atcam_region *aregion);
266 int mlxsw_sp_acl_erps_init(struct mlxsw_sp *mlxsw_sp,
267 			   struct mlxsw_sp_acl_atcam *atcam);
268 void mlxsw_sp_acl_erps_fini(struct mlxsw_sp *mlxsw_sp,
269 			    struct mlxsw_sp_acl_atcam *atcam);
270 
271 struct mlxsw_sp_acl_bf;
272 
273 int
274 mlxsw_sp_acl_bf_entry_add(struct mlxsw_sp *mlxsw_sp,
275 			  struct mlxsw_sp_acl_bf *bf,
276 			  struct mlxsw_sp_acl_atcam_region *aregion,
277 			  unsigned int erp_bank,
278 			  struct mlxsw_sp_acl_atcam_entry *aentry);
279 void
280 mlxsw_sp_acl_bf_entry_del(struct mlxsw_sp *mlxsw_sp,
281 			  struct mlxsw_sp_acl_bf *bf,
282 			  struct mlxsw_sp_acl_atcam_region *aregion,
283 			  unsigned int erp_bank,
284 			  struct mlxsw_sp_acl_atcam_entry *aentry);
285 struct mlxsw_sp_acl_bf *
286 mlxsw_sp_acl_bf_init(struct mlxsw_sp *mlxsw_sp, unsigned int num_erp_banks);
287 void mlxsw_sp_acl_bf_fini(struct mlxsw_sp_acl_bf *bf);
288 
289 #endif
290