spectrum_acl_tcam.h 10.1 KB
Newer Older
1 2
/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
/* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */
3 4 5 6 7 8 9 10 11 12 13

#ifndef _MLXSW_SPECTRUM_ACL_TCAM_H
#define _MLXSW_SPECTRUM_ACL_TCAM_H

#include <linux/list.h>
#include <linux/parman.h>

#include "reg.h"
#include "spectrum.h"
#include "core_acl_flex_keys.h"

14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
struct mlxsw_sp_acl_tcam {
	unsigned long *used_regions; /* bit array */
	unsigned int max_regions;
	unsigned long *used_groups;  /* bit array */
	unsigned int max_groups;
	unsigned int max_group_size;
	unsigned long priv[0];
	/* priv has to be always the last item */
};

size_t mlxsw_sp_acl_tcam_priv_size(struct mlxsw_sp *mlxsw_sp);
int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,
			   struct mlxsw_sp_acl_tcam *tcam);
void mlxsw_sp_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp,
			    struct mlxsw_sp_acl_tcam *tcam);
29 30 31
int mlxsw_sp_acl_tcam_priority_get(struct mlxsw_sp *mlxsw_sp,
				   struct mlxsw_sp_acl_rule_info *rulei,
				   u32 *priority, bool fillup_priority);
32 33 34 35

struct mlxsw_sp_acl_profile_ops {
	size_t ruleset_priv_size;
	int (*ruleset_add)(struct mlxsw_sp *mlxsw_sp,
36 37
			   struct mlxsw_sp_acl_tcam *tcam, void *ruleset_priv,
			   struct mlxsw_afk_element_usage *tmplt_elusage);
38 39 40 41 42 43 44 45 46 47 48 49 50
	void (*ruleset_del)(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv);
	int (*ruleset_bind)(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv,
			    struct mlxsw_sp_port *mlxsw_sp_port,
			    bool ingress);
	void (*ruleset_unbind)(struct mlxsw_sp *mlxsw_sp, void *ruleset_priv,
			       struct mlxsw_sp_port *mlxsw_sp_port,
			       bool ingress);
	u16 (*ruleset_group_id)(void *ruleset_priv);
	size_t (*rule_priv_size)(struct mlxsw_sp *mlxsw_sp);
	int (*rule_add)(struct mlxsw_sp *mlxsw_sp,
			void *ruleset_priv, void *rule_priv,
			struct mlxsw_sp_acl_rule_info *rulei);
	void (*rule_del)(struct mlxsw_sp *mlxsw_sp, void *rule_priv);
51 52 53
	int (*rule_action_replace)(struct mlxsw_sp *mlxsw_sp,
				   void *ruleset_priv, void *rule_priv,
				   struct mlxsw_sp_acl_rule_info *rulei);
54 55 56 57 58 59 60
	int (*rule_activity_get)(struct mlxsw_sp *mlxsw_sp, void *rule_priv,
				 bool *activity);
};

const struct mlxsw_sp_acl_profile_ops *
mlxsw_sp_acl_tcam_profile_ops(struct mlxsw_sp *mlxsw_sp,
			      enum mlxsw_sp_acl_profile profile);
61 62 63 64 65 66

#define MLXSW_SP_ACL_TCAM_REGION_BASE_COUNT 16
#define MLXSW_SP_ACL_TCAM_REGION_RESIZE_STEP 16

#define MLXSW_SP_ACL_TCAM_CATCHALL_PRIO (~0U)

67 68 69
#define MLXSW_SP_ACL_TCAM_MASK_LEN \
	(MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN * BITS_PER_BYTE)

70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
struct mlxsw_sp_acl_tcam_group;

struct mlxsw_sp_acl_tcam_region {
	struct list_head list; /* Member of a TCAM group */
	struct list_head chunk_list; /* List of chunks under this region */
	struct mlxsw_sp_acl_tcam_group *group;
	enum mlxsw_reg_ptar_key_type key_type;
	u16 id; /* ACL ID and region ID - they are same */
	char tcam_region_info[MLXSW_REG_PXXX_TCAM_REGION_INFO_LEN];
	struct mlxsw_afk_key_info *key_info;
	struct mlxsw_sp *mlxsw_sp;
	unsigned long priv[0];
	/* priv has to be always the last item */
};

struct mlxsw_sp_acl_ctcam_region {
	struct parman *parman;
87
	const struct mlxsw_sp_acl_ctcam_region_ops *ops;
88 89 90 91 92 93 94 95 96 97 98
	struct mlxsw_sp_acl_tcam_region *region;
};

struct mlxsw_sp_acl_ctcam_chunk {
	struct parman_prio parman_prio;
};

struct mlxsw_sp_acl_ctcam_entry {
	struct parman_item parman_item;
};

99 100 101 102 103 104 105 106 107 108 109 110 111
struct mlxsw_sp_acl_ctcam_region_ops {
	int (*entry_insert)(struct mlxsw_sp_acl_ctcam_region *cregion,
			    struct mlxsw_sp_acl_ctcam_entry *centry,
			    const char *mask);
	void (*entry_remove)(struct mlxsw_sp_acl_ctcam_region *cregion,
			     struct mlxsw_sp_acl_ctcam_entry *centry);
};

int
mlxsw_sp_acl_ctcam_region_init(struct mlxsw_sp *mlxsw_sp,
			       struct mlxsw_sp_acl_ctcam_region *cregion,
			       struct mlxsw_sp_acl_tcam_region *region,
			       const struct mlxsw_sp_acl_ctcam_region_ops *ops);
112 113 114 115 116 117 118 119 120
void mlxsw_sp_acl_ctcam_region_fini(struct mlxsw_sp_acl_ctcam_region *cregion);
void mlxsw_sp_acl_ctcam_chunk_init(struct mlxsw_sp_acl_ctcam_region *cregion,
				   struct mlxsw_sp_acl_ctcam_chunk *cchunk,
				   unsigned int priority);
void mlxsw_sp_acl_ctcam_chunk_fini(struct mlxsw_sp_acl_ctcam_chunk *cchunk);
int mlxsw_sp_acl_ctcam_entry_add(struct mlxsw_sp *mlxsw_sp,
				 struct mlxsw_sp_acl_ctcam_region *cregion,
				 struct mlxsw_sp_acl_ctcam_chunk *cchunk,
				 struct mlxsw_sp_acl_ctcam_entry *centry,
121 122
				 struct mlxsw_sp_acl_rule_info *rulei,
				 bool fillup_priority);
123 124 125 126
void mlxsw_sp_acl_ctcam_entry_del(struct mlxsw_sp *mlxsw_sp,
				  struct mlxsw_sp_acl_ctcam_region *cregion,
				  struct mlxsw_sp_acl_ctcam_chunk *cchunk,
				  struct mlxsw_sp_acl_ctcam_entry *centry);
127 128 129 130 131
int mlxsw_sp_acl_ctcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
					    struct mlxsw_sp_acl_ctcam_region *cregion,
					    struct mlxsw_sp_acl_ctcam_chunk *cchunk,
					    struct mlxsw_sp_acl_ctcam_entry *centry,
					    struct mlxsw_sp_acl_rule_info *rulei);
132 133 134 135 136 137
static inline unsigned int
mlxsw_sp_acl_ctcam_entry_offset(struct mlxsw_sp_acl_ctcam_entry *centry)
{
	return centry->parman_item.index;
}

138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
enum mlxsw_sp_acl_atcam_region_type {
	MLXSW_SP_ACL_ATCAM_REGION_TYPE_2KB,
	MLXSW_SP_ACL_ATCAM_REGION_TYPE_4KB,
	MLXSW_SP_ACL_ATCAM_REGION_TYPE_8KB,
	MLXSW_SP_ACL_ATCAM_REGION_TYPE_12KB,
	__MLXSW_SP_ACL_ATCAM_REGION_TYPE_MAX,
};

#define MLXSW_SP_ACL_ATCAM_REGION_TYPE_MAX \
	(__MLXSW_SP_ACL_ATCAM_REGION_TYPE_MAX - 1)

struct mlxsw_sp_acl_atcam {
	struct mlxsw_sp_acl_erp_core *erp_core;
};

struct mlxsw_sp_acl_atcam_region {
154
	struct rhashtable entries_ht; /* A-TCAM only */
155
	struct mlxsw_sp_acl_ctcam_region cregion;
156
	const struct mlxsw_sp_acl_atcam_region_ops *ops;
157 158 159 160
	struct mlxsw_sp_acl_tcam_region *region;
	struct mlxsw_sp_acl_atcam *atcam;
	enum mlxsw_sp_acl_atcam_region_type type;
	struct mlxsw_sp_acl_erp_table *erp_table;
161 162 163 164
	void *priv;
};

struct mlxsw_sp_acl_atcam_entry_ht_key {
165 166 167
	char enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded key,
							    * minus delta bits.
							    */
168 169 170 171 172 173 174 175 176 177
	u8 erp_id;
};

struct mlxsw_sp_acl_atcam_chunk {
	struct mlxsw_sp_acl_ctcam_chunk cchunk;
};

struct mlxsw_sp_acl_atcam_entry {
	struct rhash_head ht_node;
	struct mlxsw_sp_acl_atcam_entry_ht_key ht_key;
178 179 180 181 182 183
	char full_enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded key */
	struct {
		u16 start;
		u8 mask;
		u8 value;
	} delta_info;
184 185
	struct mlxsw_sp_acl_ctcam_entry centry;
	struct mlxsw_sp_acl_atcam_lkey_id *lkey_id;
186
	struct mlxsw_sp_acl_erp_mask *erp_mask;
187 188
};

189 190 191 192 193 194 195 196 197 198 199 200
static inline struct mlxsw_sp_acl_atcam_region *
mlxsw_sp_acl_tcam_cregion_aregion(struct mlxsw_sp_acl_ctcam_region *cregion)
{
	return container_of(cregion, struct mlxsw_sp_acl_atcam_region, cregion);
}

static inline struct mlxsw_sp_acl_atcam_entry *
mlxsw_sp_acl_tcam_centry_aentry(struct mlxsw_sp_acl_ctcam_entry *centry)
{
	return container_of(centry, struct mlxsw_sp_acl_atcam_entry, centry);
}

201 202
int mlxsw_sp_acl_atcam_region_associate(struct mlxsw_sp *mlxsw_sp,
					u16 region_id);
203 204 205 206 207 208
int
mlxsw_sp_acl_atcam_region_init(struct mlxsw_sp *mlxsw_sp,
			       struct mlxsw_sp_acl_atcam *atcam,
			       struct mlxsw_sp_acl_atcam_region *aregion,
			       struct mlxsw_sp_acl_tcam_region *region,
			       const struct mlxsw_sp_acl_ctcam_region_ops *ops);
209
void mlxsw_sp_acl_atcam_region_fini(struct mlxsw_sp_acl_atcam_region *aregion);
210 211 212 213 214 215 216 217 218 219 220 221 222
void mlxsw_sp_acl_atcam_chunk_init(struct mlxsw_sp_acl_atcam_region *aregion,
				   struct mlxsw_sp_acl_atcam_chunk *achunk,
				   unsigned int priority);
void mlxsw_sp_acl_atcam_chunk_fini(struct mlxsw_sp_acl_atcam_chunk *achunk);
int mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp,
				 struct mlxsw_sp_acl_atcam_region *aregion,
				 struct mlxsw_sp_acl_atcam_chunk *achunk,
				 struct mlxsw_sp_acl_atcam_entry *aentry,
				 struct mlxsw_sp_acl_rule_info *rulei);
void mlxsw_sp_acl_atcam_entry_del(struct mlxsw_sp *mlxsw_sp,
				  struct mlxsw_sp_acl_atcam_region *aregion,
				  struct mlxsw_sp_acl_atcam_chunk *achunk,
				  struct mlxsw_sp_acl_atcam_entry *aentry);
223 224 225 226 227
int mlxsw_sp_acl_atcam_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
					    struct mlxsw_sp_acl_atcam_region *aregion,
					    struct mlxsw_sp_acl_atcam_chunk *achunk,
					    struct mlxsw_sp_acl_atcam_entry *aentry,
					    struct mlxsw_sp_acl_rule_info *rulei);
228 229 230 231
int mlxsw_sp_acl_atcam_init(struct mlxsw_sp *mlxsw_sp,
			    struct mlxsw_sp_acl_atcam *atcam);
void mlxsw_sp_acl_atcam_fini(struct mlxsw_sp *mlxsw_sp,
			     struct mlxsw_sp_acl_atcam *atcam);
232

233 234 235 236 237 238 239 240 241
struct mlxsw_sp_acl_erp_delta;

u16 mlxsw_sp_acl_erp_delta_start(const struct mlxsw_sp_acl_erp_delta *delta);
u8 mlxsw_sp_acl_erp_delta_mask(const struct mlxsw_sp_acl_erp_delta *delta);
u8 mlxsw_sp_acl_erp_delta_value(const struct mlxsw_sp_acl_erp_delta *delta,
				const char *enc_key);
void mlxsw_sp_acl_erp_delta_clear(const struct mlxsw_sp_acl_erp_delta *delta,
				  const char *enc_key);

242
struct mlxsw_sp_acl_erp_mask;
243

244 245 246
bool
mlxsw_sp_acl_erp_mask_is_ctcam(const struct mlxsw_sp_acl_erp_mask *erp_mask);
u8 mlxsw_sp_acl_erp_mask_erp_id(const struct mlxsw_sp_acl_erp_mask *erp_mask);
247 248
const struct mlxsw_sp_acl_erp_delta *
mlxsw_sp_acl_erp_delta(const struct mlxsw_sp_acl_erp_mask *erp_mask);
249 250 251 252 253
struct mlxsw_sp_acl_erp_mask *
mlxsw_sp_acl_erp_mask_get(struct mlxsw_sp_acl_atcam_region *aregion,
			  const char *mask, bool ctcam);
void mlxsw_sp_acl_erp_mask_put(struct mlxsw_sp_acl_atcam_region *aregion,
			       struct mlxsw_sp_acl_erp_mask *erp_mask);
254 255 256 257 258 259 260
int mlxsw_sp_acl_erp_region_init(struct mlxsw_sp_acl_atcam_region *aregion);
void mlxsw_sp_acl_erp_region_fini(struct mlxsw_sp_acl_atcam_region *aregion);
int mlxsw_sp_acl_erps_init(struct mlxsw_sp *mlxsw_sp,
			   struct mlxsw_sp_acl_atcam *atcam);
void mlxsw_sp_acl_erps_fini(struct mlxsw_sp *mlxsw_sp,
			    struct mlxsw_sp_acl_atcam *atcam);

261 262
struct mlxsw_sp_acl_bf;

263 264 265 266 267 268 269 270 271 272 273 274
int
mlxsw_sp_acl_bf_entry_add(struct mlxsw_sp *mlxsw_sp,
			  struct mlxsw_sp_acl_bf *bf,
			  struct mlxsw_sp_acl_atcam_region *aregion,
			  unsigned int erp_bank,
			  struct mlxsw_sp_acl_atcam_entry *aentry);
void
mlxsw_sp_acl_bf_entry_del(struct mlxsw_sp *mlxsw_sp,
			  struct mlxsw_sp_acl_bf *bf,
			  struct mlxsw_sp_acl_atcam_region *aregion,
			  unsigned int erp_bank,
			  struct mlxsw_sp_acl_atcam_entry *aentry);
275 276 277 278
struct mlxsw_sp_acl_bf *
mlxsw_sp_acl_bf_init(struct mlxsw_sp *mlxsw_sp, unsigned int num_erp_banks);
void mlxsw_sp_acl_bf_fini(struct mlxsw_sp_acl_bf *bf);

279
#endif