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