306 lines
11 KiB
C
306 lines
11 KiB
C
|
/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
|
||
|
/* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */
|
||
|
|
||
|
#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"
|
||
|
|
||
|
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;
|
||
|
struct mutex lock; /* guards vregion list */
|
||
|
struct list_head vregion_list;
|
||
|
u32 vregion_rehash_intrvl; /* ms */
|
||
|
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);
|
||
|
u32 mlxsw_sp_acl_tcam_vregion_rehash_intrvl_get(struct mlxsw_sp *mlxsw_sp,
|
||
|
struct mlxsw_sp_acl_tcam *tcam);
|
||
|
int mlxsw_sp_acl_tcam_vregion_rehash_intrvl_set(struct mlxsw_sp *mlxsw_sp,
|
||
|
struct mlxsw_sp_acl_tcam *tcam,
|
||
|
u32 val);
|
||
|
int mlxsw_sp_acl_tcam_priority_get(struct mlxsw_sp *mlxsw_sp,
|
||
|
struct mlxsw_sp_acl_rule_info *rulei,
|
||
|
u32 *priority, bool fillup_priority);
|
||
|
|
||
|
struct mlxsw_sp_acl_profile_ops {
|
||
|
size_t ruleset_priv_size;
|
||
|
int (*ruleset_add)(struct mlxsw_sp *mlxsw_sp,
|
||
|
struct mlxsw_sp_acl_tcam *tcam, void *ruleset_priv,
|
||
|
struct mlxsw_afk_element_usage *tmplt_elusage);
|
||
|
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;
|
||
|
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_action_replace)(struct mlxsw_sp *mlxsw_sp, void *rule_priv,
|
||
|
struct mlxsw_sp_acl_rule_info *rulei);
|
||
|
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);
|
||
|
|
||
|
#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)
|
||
|
|
||
|
#define MLXSW_SP_ACL_TCAM_MASK_LEN \
|
||
|
(MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN * BITS_PER_BYTE)
|
||
|
|
||
|
struct mlxsw_sp_acl_tcam_group;
|
||
|
struct mlxsw_sp_acl_tcam_vregion;
|
||
|
|
||
|
struct mlxsw_sp_acl_tcam_region {
|
||
|
struct mlxsw_sp_acl_tcam_vregion *vregion;
|
||
|
struct mlxsw_sp_acl_tcam_group *group;
|
||
|
struct list_head list; /* Member of a TCAM 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;
|
||
|
const struct mlxsw_sp_acl_ctcam_region_ops *ops;
|
||
|
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;
|
||
|
};
|
||
|
|
||
|
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);
|
||
|
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,
|
||
|
struct mlxsw_sp_acl_rule_info *rulei,
|
||
|
bool fillup_priority);
|
||
|
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);
|
||
|
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_entry *centry,
|
||
|
struct mlxsw_sp_acl_rule_info *rulei);
|
||
|
static inline unsigned int
|
||
|
mlxsw_sp_acl_ctcam_entry_offset(struct mlxsw_sp_acl_ctcam_entry *centry)
|
||
|
{
|
||
|
return centry->parman_item.index;
|
||
|
}
|
||
|
|
||
|
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 {
|
||
|
struct rhashtable entries_ht; /* A-TCAM only */
|
||
|
struct list_head entries_list; /* A-TCAM only */
|
||
|
struct mlxsw_sp_acl_ctcam_region cregion;
|
||
|
const struct mlxsw_sp_acl_atcam_region_ops *ops;
|
||
|
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;
|
||
|
void *priv;
|
||
|
};
|
||
|
|
||
|
struct mlxsw_sp_acl_atcam_entry_ht_key {
|
||
|
char full_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 list_head list; /* Member in entries_list */
|
||
|
struct mlxsw_sp_acl_atcam_entry_ht_key ht_key;
|
||
|
char enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded key,
|
||
|
* minus delta bits.
|
||
|
*/
|
||
|
struct {
|
||
|
u16 start;
|
||
|
u8 mask;
|
||
|
u8 value;
|
||
|
} delta_info;
|
||
|
struct mlxsw_sp_acl_ctcam_entry centry;
|
||
|
struct mlxsw_sp_acl_atcam_lkey_id *lkey_id;
|
||
|
struct mlxsw_sp_acl_erp_mask *erp_mask;
|
||
|
};
|
||
|
|
||
|
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);
|
||
|
}
|
||
|
|
||
|
int mlxsw_sp_acl_atcam_region_associate(struct mlxsw_sp *mlxsw_sp,
|
||
|
u16 region_id);
|
||
|
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,
|
||
|
void *hints_priv,
|
||
|
const struct mlxsw_sp_acl_ctcam_region_ops *ops);
|
||
|
void mlxsw_sp_acl_atcam_region_fini(struct mlxsw_sp_acl_atcam_region *aregion);
|
||
|
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);
|
||
|
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_entry *aentry,
|
||
|
struct mlxsw_sp_acl_rule_info *rulei);
|
||
|
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);
|
||
|
void *
|
||
|
mlxsw_sp_acl_atcam_rehash_hints_get(struct mlxsw_sp_acl_atcam_region *aregion);
|
||
|
void mlxsw_sp_acl_atcam_rehash_hints_put(void *hints_priv);
|
||
|
|
||
|
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);
|
||
|
|
||
|
struct mlxsw_sp_acl_erp_mask;
|
||
|
|
||
|
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);
|
||
|
const struct mlxsw_sp_acl_erp_delta *
|
||
|
mlxsw_sp_acl_erp_delta(const struct mlxsw_sp_acl_erp_mask *erp_mask);
|
||
|
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);
|
||
|
int mlxsw_sp_acl_erp_bf_insert(struct mlxsw_sp *mlxsw_sp,
|
||
|
struct mlxsw_sp_acl_atcam_region *aregion,
|
||
|
struct mlxsw_sp_acl_erp_mask *erp_mask,
|
||
|
struct mlxsw_sp_acl_atcam_entry *aentry);
|
||
|
void mlxsw_sp_acl_erp_bf_remove(struct mlxsw_sp *mlxsw_sp,
|
||
|
struct mlxsw_sp_acl_atcam_region *aregion,
|
||
|
struct mlxsw_sp_acl_erp_mask *erp_mask,
|
||
|
struct mlxsw_sp_acl_atcam_entry *aentry);
|
||
|
void *
|
||
|
mlxsw_sp_acl_erp_rehash_hints_get(struct mlxsw_sp_acl_atcam_region *aregion);
|
||
|
void mlxsw_sp_acl_erp_rehash_hints_put(void *hints_priv);
|
||
|
int mlxsw_sp_acl_erp_region_init(struct mlxsw_sp_acl_atcam_region *aregion,
|
||
|
void *hints_priv);
|
||
|
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);
|
||
|
|
||
|
struct mlxsw_sp_acl_bf;
|
||
|
|
||
|
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);
|
||
|
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);
|
||
|
|
||
|
#endif
|