Commit 135fd957 authored by Nir Dotan's avatar Nir Dotan Committed by David S. Miller

mlxsw: spectrum_acl: Update Bloom filter on eRP transitions

Bloom filter update is required only for rules which reside on an
eRP. When the region has only a single rule pattern then eRP table
is not used, however insertion of another pattern would trigger a
move to an active eRP table so it is imperative to update the Bloom
filter with all previously configured rules.

Add a method that updates Bloom filter entries for all rules
currently configured in the region, on the event of a transition
from master mask to eRP, or vice versa. For that purpose, maintain
a list of all A-TCAM rules within mlxsw_sp_acl_atcam_region.
Signed-off-by: default avatarNir Dotan <nird@mellanox.com>
Signed-off-by: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8c81b743
...@@ -323,6 +323,7 @@ mlxsw_sp_acl_atcam_region_init(struct mlxsw_sp *mlxsw_sp, ...@@ -323,6 +323,7 @@ mlxsw_sp_acl_atcam_region_init(struct mlxsw_sp *mlxsw_sp,
aregion->region = region; aregion->region = region;
aregion->atcam = atcam; aregion->atcam = atcam;
mlxsw_sp_acl_atcam_region_type_init(aregion); mlxsw_sp_acl_atcam_region_type_init(aregion);
INIT_LIST_HEAD(&aregion->entries_list);
err = rhashtable_init(&aregion->entries_ht, err = rhashtable_init(&aregion->entries_ht,
&mlxsw_sp_acl_atcam_entries_ht_params); &mlxsw_sp_acl_atcam_entries_ht_params);
...@@ -356,6 +357,7 @@ void mlxsw_sp_acl_atcam_region_fini(struct mlxsw_sp_acl_atcam_region *aregion) ...@@ -356,6 +357,7 @@ void mlxsw_sp_acl_atcam_region_fini(struct mlxsw_sp_acl_atcam_region *aregion)
mlxsw_sp_acl_erp_region_fini(aregion); mlxsw_sp_acl_erp_region_fini(aregion);
aregion->ops->fini(aregion); aregion->ops->fini(aregion);
rhashtable_destroy(&aregion->entries_ht); rhashtable_destroy(&aregion->entries_ht);
WARN_ON(!list_empty(&aregion->entries_list));
} }
void mlxsw_sp_acl_atcam_chunk_init(struct mlxsw_sp_acl_atcam_region *aregion, void mlxsw_sp_acl_atcam_chunk_init(struct mlxsw_sp_acl_atcam_region *aregion,
...@@ -499,6 +501,12 @@ __mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp, ...@@ -499,6 +501,12 @@ __mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp,
mlxsw_sp_acl_erp_delta_value(delta, aentry->full_enc_key); mlxsw_sp_acl_erp_delta_value(delta, aentry->full_enc_key);
mlxsw_sp_acl_erp_delta_clear(delta, aentry->ht_key.enc_key); mlxsw_sp_acl_erp_delta_clear(delta, aentry->ht_key.enc_key);
/* Add rule to the list of A-TCAM rules, assuming this
* rule is intended to A-TCAM. In case this rule does
* not fit into A-TCAM it will be removed from the list.
*/
list_add(&aentry->list, &aregion->entries_list);
/* We can't insert identical rules into the A-TCAM, so fail and /* We can't insert identical rules into the A-TCAM, so fail and
* let the rule spill into C-TCAM * let the rule spill into C-TCAM
*/ */
...@@ -528,6 +536,7 @@ __mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp, ...@@ -528,6 +536,7 @@ __mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp,
rhashtable_remove_fast(&aregion->entries_ht, &aentry->ht_node, rhashtable_remove_fast(&aregion->entries_ht, &aentry->ht_node,
mlxsw_sp_acl_atcam_entries_ht_params); mlxsw_sp_acl_atcam_entries_ht_params);
err_rhashtable_insert: err_rhashtable_insert:
list_del(&aentry->list);
mlxsw_sp_acl_erp_mask_put(aregion, erp_mask); mlxsw_sp_acl_erp_mask_put(aregion, erp_mask);
return err; return err;
} }
...@@ -541,6 +550,7 @@ __mlxsw_sp_acl_atcam_entry_del(struct mlxsw_sp *mlxsw_sp, ...@@ -541,6 +550,7 @@ __mlxsw_sp_acl_atcam_entry_del(struct mlxsw_sp *mlxsw_sp,
mlxsw_sp_acl_erp_bf_remove(mlxsw_sp, aregion, aentry->erp_mask, aentry); mlxsw_sp_acl_erp_bf_remove(mlxsw_sp, aregion, aentry->erp_mask, aentry);
rhashtable_remove_fast(&aregion->entries_ht, &aentry->ht_node, rhashtable_remove_fast(&aregion->entries_ht, &aentry->ht_node,
mlxsw_sp_acl_atcam_entries_ht_params); mlxsw_sp_acl_atcam_entries_ht_params);
list_del(&aentry->list);
mlxsw_sp_acl_erp_mask_put(aregion, aentry->erp_mask); mlxsw_sp_acl_erp_mask_put(aregion, aentry->erp_mask);
} }
......
...@@ -517,6 +517,48 @@ mlxsw_sp_acl_erp_table_expand(struct mlxsw_sp_acl_erp_table *erp_table) ...@@ -517,6 +517,48 @@ mlxsw_sp_acl_erp_table_expand(struct mlxsw_sp_acl_erp_table *erp_table)
return err; return err;
} }
static int
mlxsw_acl_erp_table_bf_add(struct mlxsw_sp_acl_erp_table *erp_table,
struct mlxsw_sp_acl_erp *erp)
{
struct mlxsw_sp_acl_atcam_region *aregion = erp_table->aregion;
unsigned int erp_bank = mlxsw_sp_acl_erp_bank_get(erp);
struct mlxsw_sp_acl_atcam_entry *aentry;
int err;
list_for_each_entry(aentry, &aregion->entries_list, list) {
err = mlxsw_sp_acl_bf_entry_add(aregion->region->mlxsw_sp,
erp_table->erp_core->bf,
aregion, erp_bank, aentry);
if (err)
goto bf_entry_add_err;
}
return 0;
bf_entry_add_err:
list_for_each_entry_continue_reverse(aentry, &aregion->entries_list,
list)
mlxsw_sp_acl_bf_entry_del(aregion->region->mlxsw_sp,
erp_table->erp_core->bf,
aregion, erp_bank, aentry);
return err;
}
static void
mlxsw_acl_erp_table_bf_del(struct mlxsw_sp_acl_erp_table *erp_table,
struct mlxsw_sp_acl_erp *erp)
{
struct mlxsw_sp_acl_atcam_region *aregion = erp_table->aregion;
unsigned int erp_bank = mlxsw_sp_acl_erp_bank_get(erp);
struct mlxsw_sp_acl_atcam_entry *aentry;
list_for_each_entry_reverse(aentry, &aregion->entries_list, list)
mlxsw_sp_acl_bf_entry_del(aregion->region->mlxsw_sp,
erp_table->erp_core->bf,
aregion, erp_bank, aentry);
}
static int static int
mlxsw_sp_acl_erp_region_table_trans(struct mlxsw_sp_acl_erp_table *erp_table) mlxsw_sp_acl_erp_region_table_trans(struct mlxsw_sp_acl_erp_table *erp_table)
{ {
...@@ -551,6 +593,14 @@ mlxsw_sp_acl_erp_region_table_trans(struct mlxsw_sp_acl_erp_table *erp_table) ...@@ -551,6 +593,14 @@ mlxsw_sp_acl_erp_region_table_trans(struct mlxsw_sp_acl_erp_table *erp_table)
if (err) if (err)
goto err_table_master_rp_add; goto err_table_master_rp_add;
/* Update Bloom filter before enabling eRP table, as rules
* on the master RP were not set to Bloom filter up to this
* point.
*/
err = mlxsw_acl_erp_table_bf_add(erp_table, master_rp);
if (err)
goto err_table_bf_add;
err = mlxsw_sp_acl_erp_table_enable(erp_table, false); err = mlxsw_sp_acl_erp_table_enable(erp_table, false);
if (err) if (err)
goto err_table_enable; goto err_table_enable;
...@@ -558,6 +608,8 @@ mlxsw_sp_acl_erp_region_table_trans(struct mlxsw_sp_acl_erp_table *erp_table) ...@@ -558,6 +608,8 @@ mlxsw_sp_acl_erp_region_table_trans(struct mlxsw_sp_acl_erp_table *erp_table)
return 0; return 0;
err_table_enable: err_table_enable:
mlxsw_acl_erp_table_bf_del(erp_table, master_rp);
err_table_bf_add:
mlxsw_sp_acl_erp_table_erp_del(master_rp); mlxsw_sp_acl_erp_table_erp_del(master_rp);
err_table_master_rp_add: err_table_master_rp_add:
__clear_bit(master_rp->index, erp_table->erp_index_bitmap); __clear_bit(master_rp->index, erp_table->erp_index_bitmap);
...@@ -578,6 +630,7 @@ mlxsw_sp_acl_erp_region_master_mask_trans(struct mlxsw_sp_acl_erp_table *erp_tab ...@@ -578,6 +630,7 @@ mlxsw_sp_acl_erp_region_master_mask_trans(struct mlxsw_sp_acl_erp_table *erp_tab
master_rp = mlxsw_sp_acl_erp_table_master_rp(erp_table); master_rp = mlxsw_sp_acl_erp_table_master_rp(erp_table);
if (!master_rp) if (!master_rp)
return; return;
mlxsw_acl_erp_table_bf_del(erp_table, master_rp);
mlxsw_sp_acl_erp_table_erp_del(master_rp); mlxsw_sp_acl_erp_table_erp_del(master_rp);
__clear_bit(master_rp->index, erp_table->erp_index_bitmap); __clear_bit(master_rp->index, erp_table->erp_index_bitmap);
mlxsw_sp_acl_erp_table_free(erp_core, erp_table->num_max_atcam_erps, mlxsw_sp_acl_erp_table_free(erp_core, erp_table->num_max_atcam_erps,
......
...@@ -152,6 +152,7 @@ struct mlxsw_sp_acl_atcam { ...@@ -152,6 +152,7 @@ struct mlxsw_sp_acl_atcam {
struct mlxsw_sp_acl_atcam_region { struct mlxsw_sp_acl_atcam_region {
struct rhashtable entries_ht; /* A-TCAM only */ struct rhashtable entries_ht; /* A-TCAM only */
struct list_head entries_list; /* A-TCAM only */
struct mlxsw_sp_acl_ctcam_region cregion; struct mlxsw_sp_acl_ctcam_region cregion;
const struct mlxsw_sp_acl_atcam_region_ops *ops; const struct mlxsw_sp_acl_atcam_region_ops *ops;
struct mlxsw_sp_acl_tcam_region *region; struct mlxsw_sp_acl_tcam_region *region;
...@@ -174,6 +175,7 @@ struct mlxsw_sp_acl_atcam_chunk { ...@@ -174,6 +175,7 @@ struct mlxsw_sp_acl_atcam_chunk {
struct mlxsw_sp_acl_atcam_entry { struct mlxsw_sp_acl_atcam_entry {
struct rhash_head ht_node; struct rhash_head ht_node;
struct list_head list; /* Member in entries_list */
struct mlxsw_sp_acl_atcam_entry_ht_key ht_key; struct mlxsw_sp_acl_atcam_entry_ht_key ht_key;
char full_enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded key */ char full_enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded key */
struct { struct {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment