Commit cb56e214 authored by Jiri Pirko's avatar Jiri Pirko Committed by David S. Miller
Browse files

mlxsw: spectrum_acl: Include delta bits into hashtable key



Currently only ERP mask masked bits in key are considered for
the hashtable key. That leads to false negative collisions
and fallbacks to C-TCAM in case two keys differ only in delta bits.

Fix this by taking full encoded key as a hashtable key,
including delta bits.

Reported-by: default avatarNir Dotan <nird@mellanox.com>
Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 804a15cd
Loading
Loading
Loading
Loading
+10 −11
Original line number Original line Diff line number Diff line
@@ -390,8 +390,7 @@ mlxsw_sp_acl_atcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp,
	if (err)
	if (err)
		return err;
		return err;


	lkey_id = aregion->ops->lkey_id_get(aregion, aentry->ht_key.enc_key,
	lkey_id = aregion->ops->lkey_id_get(aregion, aentry->enc_key, erp_id);
					    erp_id);
	if (IS_ERR(lkey_id))
	if (IS_ERR(lkey_id))
		return PTR_ERR(lkey_id);
		return PTR_ERR(lkey_id);
	aentry->lkey_id = lkey_id;
	aentry->lkey_id = lkey_id;
@@ -399,7 +398,7 @@ mlxsw_sp_acl_atcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp,
	kvdl_index = mlxsw_afa_block_first_kvdl_index(rulei->act_block);
	kvdl_index = mlxsw_afa_block_first_kvdl_index(rulei->act_block);
	mlxsw_reg_ptce3_pack(ptce3_pl, true, MLXSW_REG_PTCE3_OP_WRITE_WRITE,
	mlxsw_reg_ptce3_pack(ptce3_pl, true, MLXSW_REG_PTCE3_OP_WRITE_WRITE,
			     priority, region->tcam_region_info,
			     priority, region->tcam_region_info,
			     aentry->ht_key.enc_key, erp_id,
			     aentry->enc_key, erp_id,
			     aentry->delta_info.start,
			     aentry->delta_info.start,
			     aentry->delta_info.mask,
			     aentry->delta_info.mask,
			     aentry->delta_info.value,
			     aentry->delta_info.value,
@@ -424,12 +423,11 @@ mlxsw_sp_acl_atcam_region_entry_remove(struct mlxsw_sp *mlxsw_sp,
	struct mlxsw_sp_acl_atcam_lkey_id *lkey_id = aentry->lkey_id;
	struct mlxsw_sp_acl_atcam_lkey_id *lkey_id = aentry->lkey_id;
	struct mlxsw_sp_acl_tcam_region *region = aregion->region;
	struct mlxsw_sp_acl_tcam_region *region = aregion->region;
	u8 erp_id = mlxsw_sp_acl_erp_mask_erp_id(aentry->erp_mask);
	u8 erp_id = mlxsw_sp_acl_erp_mask_erp_id(aentry->erp_mask);
	char *enc_key = aentry->ht_key.enc_key;
	char ptce3_pl[MLXSW_REG_PTCE3_LEN];
	char ptce3_pl[MLXSW_REG_PTCE3_LEN];


	mlxsw_reg_ptce3_pack(ptce3_pl, false, MLXSW_REG_PTCE3_OP_WRITE_WRITE, 0,
	mlxsw_reg_ptce3_pack(ptce3_pl, false, MLXSW_REG_PTCE3_OP_WRITE_WRITE, 0,
			     region->tcam_region_info,
			     region->tcam_region_info,
			     enc_key, erp_id,
			     aentry->enc_key, erp_id,
			     aentry->delta_info.start,
			     aentry->delta_info.start,
			     aentry->delta_info.mask,
			     aentry->delta_info.mask,
			     aentry->delta_info.value,
			     aentry->delta_info.value,
@@ -458,7 +456,7 @@ mlxsw_sp_acl_atcam_region_entry_action_replace(struct mlxsw_sp *mlxsw_sp,
	kvdl_index = mlxsw_afa_block_first_kvdl_index(rulei->act_block);
	kvdl_index = mlxsw_afa_block_first_kvdl_index(rulei->act_block);
	mlxsw_reg_ptce3_pack(ptce3_pl, true, MLXSW_REG_PTCE3_OP_WRITE_UPDATE,
	mlxsw_reg_ptce3_pack(ptce3_pl, true, MLXSW_REG_PTCE3_OP_WRITE_UPDATE,
			     priority, region->tcam_region_info,
			     priority, region->tcam_region_info,
			     aentry->ht_key.enc_key, erp_id,
			     aentry->enc_key, erp_id,
			     aentry->delta_info.start,
			     aentry->delta_info.start,
			     aentry->delta_info.mask,
			     aentry->delta_info.mask,
			     aentry->delta_info.value,
			     aentry->delta_info.value,
@@ -481,15 +479,15 @@ __mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp,
	int err;
	int err;


	mlxsw_afk_encode(afk, region->key_info, &rulei->values,
	mlxsw_afk_encode(afk, region->key_info, &rulei->values,
			 aentry->full_enc_key, mask);
			 aentry->ht_key.full_enc_key, mask);


	erp_mask = mlxsw_sp_acl_erp_mask_get(aregion, mask, false);
	erp_mask = mlxsw_sp_acl_erp_mask_get(aregion, mask, false);
	if (IS_ERR(erp_mask))
	if (IS_ERR(erp_mask))
		return PTR_ERR(erp_mask);
		return PTR_ERR(erp_mask);
	aentry->erp_mask = erp_mask;
	aentry->erp_mask = erp_mask;
	aentry->ht_key.erp_id = mlxsw_sp_acl_erp_mask_erp_id(erp_mask);
	aentry->ht_key.erp_id = mlxsw_sp_acl_erp_mask_erp_id(erp_mask);
	memcpy(aentry->ht_key.enc_key, aentry->full_enc_key,
	memcpy(aentry->enc_key, aentry->ht_key.full_enc_key,
	       sizeof(aentry->ht_key.enc_key));
	       sizeof(aentry->enc_key));


	/* Compute all needed delta information and clear the delta bits
	/* Compute all needed delta information and clear the delta bits
	 * from the encrypted key.
	 * from the encrypted key.
@@ -498,8 +496,9 @@ __mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp,
	aentry->delta_info.start = mlxsw_sp_acl_erp_delta_start(delta);
	aentry->delta_info.start = mlxsw_sp_acl_erp_delta_start(delta);
	aentry->delta_info.mask = mlxsw_sp_acl_erp_delta_mask(delta);
	aentry->delta_info.mask = mlxsw_sp_acl_erp_delta_mask(delta);
	aentry->delta_info.value =
	aentry->delta_info.value =
		mlxsw_sp_acl_erp_delta_value(delta, aentry->full_enc_key);
		mlxsw_sp_acl_erp_delta_value(delta,
	mlxsw_sp_acl_erp_delta_clear(delta, aentry->ht_key.enc_key);
					     aentry->ht_key.full_enc_key);
	mlxsw_sp_acl_erp_delta_clear(delta, aentry->enc_key);


	/* Add rule to the list of A-TCAM rules, assuming this
	/* Add rule to the list of A-TCAM rules, assuming this
	 * rule is intended to A-TCAM. In case this rule does
	 * rule is intended to A-TCAM. In case this rule does
+1 −1
Original line number Original line Diff line number Diff line
@@ -133,7 +133,7 @@ mlxsw_sp_acl_bf_key_encode(struct mlxsw_sp_acl_atcam_region *aregion,
		memcpy(chunk + MLXSW_BLOOM_CHUNK_PAD_BYTES, &erp_region_id,
		memcpy(chunk + MLXSW_BLOOM_CHUNK_PAD_BYTES, &erp_region_id,
		       sizeof(erp_region_id));
		       sizeof(erp_region_id));
		memcpy(chunk + MLXSW_BLOOM_CHUNK_KEY_OFFSET,
		memcpy(chunk + MLXSW_BLOOM_CHUNK_KEY_OFFSET,
		       &aentry->ht_key.enc_key[chunk_key_offsets[chunk_index]],
		       &aentry->enc_key[chunk_key_offsets[chunk_index]],
		       MLXSW_BLOOM_CHUNK_KEY_BYTES);
		       MLXSW_BLOOM_CHUNK_KEY_BYTES);
		chunk += MLXSW_BLOOM_KEY_CHUNK_BYTES;
		chunk += MLXSW_BLOOM_KEY_CHUNK_BYTES;
	}
	}
+6 −4
Original line number Original line Diff line number Diff line
@@ -161,8 +161,8 @@ struct mlxsw_sp_acl_atcam_region {
};
};


struct mlxsw_sp_acl_atcam_entry_ht_key {
struct mlxsw_sp_acl_atcam_entry_ht_key {
	char enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded key,
	char full_enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded
							    * minus delta bits.
								 * key.
								 */
								 */
	u8 erp_id;
	u8 erp_id;
};
};
@@ -175,7 +175,9 @@ 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 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 enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded key,
							    * minus delta bits.
							    */
	struct {
	struct {
		u16 start;
		u16 start;
		u8 mask;
		u8 mask;