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