spectrum_acl_tcam.h 9.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
/*
 * drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h
 * Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved.
 * Copyright (c) 2017-2018 Jiri Pirko <jiri@mellanox.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the names of the copyright holders nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * Alternatively, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") version 2 as published by the Free
 * Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#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"

45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
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);
60 61 62
int mlxsw_sp_acl_tcam_priority_get(struct mlxsw_sp *mlxsw_sp,
				   struct mlxsw_sp_acl_rule_info *rulei,
				   u32 *priority, bool fillup_priority);
63 64 65 66

struct mlxsw_sp_acl_profile_ops {
	size_t ruleset_priv_size;
	int (*ruleset_add)(struct mlxsw_sp *mlxsw_sp,
67 68
			   struct mlxsw_sp_acl_tcam *tcam, void *ruleset_priv,
			   struct mlxsw_afk_element_usage *tmplt_elusage);
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
	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);
	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);
89 90 91 92 93 94

#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)

95 96 97
#define MLXSW_SP_ACL_TCAM_MASK_LEN \
	(MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN * BITS_PER_BYTE)

98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
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;
115
	const struct mlxsw_sp_acl_ctcam_region_ops *ops;
116 117 118 119 120 121 122 123 124 125 126
	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;
};

127 128 129 130 131 132 133 134 135 136 137 138 139
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);
140 141 142 143 144 145 146 147 148
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,
149 150
				 struct mlxsw_sp_acl_rule_info *rulei,
				 bool fillup_priority);
151 152 153 154 155 156 157 158 159 160
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);
static inline unsigned int
mlxsw_sp_acl_ctcam_entry_offset(struct mlxsw_sp_acl_ctcam_entry *centry)
{
	return centry->parman_item.index;
}

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
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 {
177
	struct rhashtable entries_ht; /* A-TCAM only */
178
	struct mlxsw_sp_acl_ctcam_region cregion;
179
	const struct mlxsw_sp_acl_atcam_region_ops *ops;
180 181 182 183
	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;
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
	void *priv;
};

struct mlxsw_sp_acl_atcam_entry_ht_key {
	char enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded key */
	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;
	struct mlxsw_sp_acl_ctcam_entry centry;
	struct mlxsw_sp_acl_atcam_lkey_id *lkey_id;
	struct mlxsw_sp_acl_erp *erp;
202 203
};

204 205 206 207 208 209 210 211 212 213 214 215
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);
}

216 217
int mlxsw_sp_acl_atcam_region_associate(struct mlxsw_sp *mlxsw_sp,
					u16 region_id);
218 219 220 221 222 223
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);
224
void mlxsw_sp_acl_atcam_region_fini(struct mlxsw_sp_acl_atcam_region *aregion);
225 226 227 228 229 230 231 232 233 234 235 236 237
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);
238 239 240 241
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);
242

243 244
struct mlxsw_sp_acl_erp;

245
bool mlxsw_sp_acl_erp_is_ctcam_erp(const struct mlxsw_sp_acl_erp *erp);
246 247 248
u8 mlxsw_sp_acl_erp_id(const struct mlxsw_sp_acl_erp *erp);
struct mlxsw_sp_acl_erp *
mlxsw_sp_acl_erp_get(struct mlxsw_sp_acl_atcam_region *aregion,
249
		     const char *mask, bool ctcam);
250 251 252 253 254 255 256 257 258
void mlxsw_sp_acl_erp_put(struct mlxsw_sp_acl_atcam_region *aregion,
			  struct mlxsw_sp_acl_erp *erp);
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);

259
#endif