Commit 4e86889b authored by David S. Miller's avatar David S. Miller

Merge branch 'mlxsw-ERP-sharing-multiple-masks'

Ido Schimmel says:

====================
mlxsw: spectrum: acl: Introduce ERP sharing by multiple masks

Jiri says:

The Spectrum-2 hardware has limitation number of ERPs per-region. In
order to accommodate more masks than number of ERPs, the hardware
supports to insert rules with delta bits. By that, the rules with masks
that differ in up-to 8 consecutive bits can share the same ERP.

Patches 1 and 2 fix couple of issues that would appear in existing
selftests after adding delta support

Patch 3 introduces a generic object aggregation library. Now it is
static, but it will get extended for recalculation of aggregations in
the future in order to reach more optimal aggregation.

Patch 4 just simply converts existing ERP code to use the objagg library
instead of a rhashtable.

Patches 5-9 do more or less small changes to prepare ground for the last
patch.

Patch 10 fills-up delta callbacks of objagg library and utilizes the
delta bits for rule insertion.

The last patch adds selftest to test the mlxsw Spectrum-2 delta flows.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 6ab6dfa6 3b423271
...@@ -10679,6 +10679,14 @@ L: linux-nfc@lists.01.org (moderated for non-subscribers) ...@@ -10679,6 +10679,14 @@ L: linux-nfc@lists.01.org (moderated for non-subscribers)
S: Supported S: Supported
F: drivers/nfc/nxp-nci F: drivers/nfc/nxp-nci
OBJAGG
M: Jiri Pirko <jiri@mellanox.com>
L: netdev@vger.kernel.org
S: Supported
F: lib/objagg.c
F: lib/test_objagg.c
F: include/linux/objagg.h
OBJTOOL OBJTOOL
M: Josh Poimboeuf <jpoimboe@redhat.com> M: Josh Poimboeuf <jpoimboe@redhat.com>
M: Peter Zijlstra <peterz@infradead.org> M: Peter Zijlstra <peterz@infradead.org>
......
...@@ -80,6 +80,7 @@ config MLXSW_SPECTRUM ...@@ -80,6 +80,7 @@ config MLXSW_SPECTRUM
depends on IPV6_GRE || IPV6_GRE=n depends on IPV6_GRE || IPV6_GRE=n
select GENERIC_ALLOCATOR select GENERIC_ALLOCATOR
select PARMAN select PARMAN
select OBJAGG
select MLXFW select MLXFW
default m default m
---help--- ---help---
......
...@@ -426,15 +426,17 @@ mlxsw_sp_afk_encode_one(const struct mlxsw_afk_element_inst *elinst, ...@@ -426,15 +426,17 @@ mlxsw_sp_afk_encode_one(const struct mlxsw_afk_element_inst *elinst,
void mlxsw_afk_encode(struct mlxsw_afk *mlxsw_afk, void mlxsw_afk_encode(struct mlxsw_afk *mlxsw_afk,
struct mlxsw_afk_key_info *key_info, struct mlxsw_afk_key_info *key_info,
struct mlxsw_afk_element_values *values, struct mlxsw_afk_element_values *values,
char *key, char *mask, int block_start, int block_end) char *key, char *mask)
{ {
unsigned int blocks_count =
mlxsw_afk_key_info_blocks_count_get(key_info);
char block_mask[MLXSW_SP_AFK_KEY_BLOCK_MAX_SIZE]; char block_mask[MLXSW_SP_AFK_KEY_BLOCK_MAX_SIZE];
char block_key[MLXSW_SP_AFK_KEY_BLOCK_MAX_SIZE]; char block_key[MLXSW_SP_AFK_KEY_BLOCK_MAX_SIZE];
const struct mlxsw_afk_element_inst *elinst; const struct mlxsw_afk_element_inst *elinst;
enum mlxsw_afk_element element; enum mlxsw_afk_element element;
int block_index, i; int block_index, i;
for (i = block_start; i <= block_end; i++) { for (i = 0; i < blocks_count; i++) {
memset(block_key, 0, MLXSW_SP_AFK_KEY_BLOCK_MAX_SIZE); memset(block_key, 0, MLXSW_SP_AFK_KEY_BLOCK_MAX_SIZE);
memset(block_mask, 0, MLXSW_SP_AFK_KEY_BLOCK_MAX_SIZE); memset(block_mask, 0, MLXSW_SP_AFK_KEY_BLOCK_MAX_SIZE);
...@@ -451,10 +453,18 @@ void mlxsw_afk_encode(struct mlxsw_afk *mlxsw_afk, ...@@ -451,10 +453,18 @@ void mlxsw_afk_encode(struct mlxsw_afk *mlxsw_afk,
values->storage.mask); values->storage.mask);
} }
if (key) mlxsw_afk->ops->encode_block(key, i, block_key);
mlxsw_afk->ops->encode_block(block_key, i, key); mlxsw_afk->ops->encode_block(mask, i, block_mask);
if (mask)
mlxsw_afk->ops->encode_block(block_mask, i, mask);
} }
} }
EXPORT_SYMBOL(mlxsw_afk_encode); EXPORT_SYMBOL(mlxsw_afk_encode);
void mlxsw_afk_clear(struct mlxsw_afk *mlxsw_afk, char *key,
int block_start, int block_end)
{
int i;
for (i = block_start; i <= block_end; i++)
mlxsw_afk->ops->clear_block(key, i);
}
EXPORT_SYMBOL(mlxsw_afk_clear);
...@@ -188,7 +188,8 @@ struct mlxsw_afk; ...@@ -188,7 +188,8 @@ struct mlxsw_afk;
struct mlxsw_afk_ops { struct mlxsw_afk_ops {
const struct mlxsw_afk_block *blocks; const struct mlxsw_afk_block *blocks;
unsigned int blocks_count; unsigned int blocks_count;
void (*encode_block)(char *block, int block_index, char *output); void (*encode_block)(char *output, int block_index, char *block);
void (*clear_block)(char *output, int block_index);
}; };
struct mlxsw_afk *mlxsw_afk_create(unsigned int max_blocks, struct mlxsw_afk *mlxsw_afk_create(unsigned int max_blocks,
...@@ -228,6 +229,8 @@ void mlxsw_afk_values_add_buf(struct mlxsw_afk_element_values *values, ...@@ -228,6 +229,8 @@ void mlxsw_afk_values_add_buf(struct mlxsw_afk_element_values *values,
void mlxsw_afk_encode(struct mlxsw_afk *mlxsw_afk, void mlxsw_afk_encode(struct mlxsw_afk *mlxsw_afk,
struct mlxsw_afk_key_info *key_info, struct mlxsw_afk_key_info *key_info,
struct mlxsw_afk_element_values *values, struct mlxsw_afk_element_values *values,
char *key, char *mask, int block_start, int block_end); char *key, char *mask);
void mlxsw_afk_clear(struct mlxsw_afk *mlxsw_afk, char *key,
int block_start, int block_end);
#endif #endif
...@@ -2834,8 +2834,9 @@ static inline void mlxsw_reg_ptce3_pack(char *payload, bool valid, ...@@ -2834,8 +2834,9 @@ static inline void mlxsw_reg_ptce3_pack(char *payload, bool valid,
u32 priority, u32 priority,
const char *tcam_region_info, const char *tcam_region_info,
const char *key, u8 erp_id, const char *key, u8 erp_id,
bool large_exists, u32 lkey_id, u16 delta_start, u8 delta_mask,
u32 action_pointer) u8 delta_value, bool large_exists,
u32 lkey_id, u32 action_pointer)
{ {
MLXSW_REG_ZERO(ptce3, payload); MLXSW_REG_ZERO(ptce3, payload);
mlxsw_reg_ptce3_v_set(payload, valid); mlxsw_reg_ptce3_v_set(payload, valid);
...@@ -2844,6 +2845,9 @@ static inline void mlxsw_reg_ptce3_pack(char *payload, bool valid, ...@@ -2844,6 +2845,9 @@ static inline void mlxsw_reg_ptce3_pack(char *payload, bool valid,
mlxsw_reg_ptce3_tcam_region_info_memcpy_to(payload, tcam_region_info); mlxsw_reg_ptce3_tcam_region_info_memcpy_to(payload, tcam_region_info);
mlxsw_reg_ptce3_flex2_key_blocks_memcpy_to(payload, key); mlxsw_reg_ptce3_flex2_key_blocks_memcpy_to(payload, key);
mlxsw_reg_ptce3_erp_id_set(payload, erp_id); mlxsw_reg_ptce3_erp_id_set(payload, erp_id);
mlxsw_reg_ptce3_delta_start_set(payload, delta_start);
mlxsw_reg_ptce3_delta_mask_set(payload, delta_mask);
mlxsw_reg_ptce3_delta_value_set(payload, delta_value);
mlxsw_reg_ptce3_large_exists_set(payload, large_exists); mlxsw_reg_ptce3_large_exists_set(payload, large_exists);
mlxsw_reg_ptce3_large_entry_key_id_set(payload, lkey_id); mlxsw_reg_ptce3_large_entry_key_id_set(payload, lkey_id);
mlxsw_reg_ptce3_action_pointer_set(payload, action_pointer); mlxsw_reg_ptce3_action_pointer_set(payload, action_pointer);
......
...@@ -34,15 +34,15 @@ mlxsw_sp2_acl_ctcam_region_entry_insert(struct mlxsw_sp_acl_ctcam_region *cregio ...@@ -34,15 +34,15 @@ mlxsw_sp2_acl_ctcam_region_entry_insert(struct mlxsw_sp_acl_ctcam_region *cregio
{ {
struct mlxsw_sp_acl_atcam_region *aregion; struct mlxsw_sp_acl_atcam_region *aregion;
struct mlxsw_sp_acl_atcam_entry *aentry; struct mlxsw_sp_acl_atcam_entry *aentry;
struct mlxsw_sp_acl_erp *erp; struct mlxsw_sp_acl_erp_mask *erp_mask;
aregion = mlxsw_sp_acl_tcam_cregion_aregion(cregion); aregion = mlxsw_sp_acl_tcam_cregion_aregion(cregion);
aentry = mlxsw_sp_acl_tcam_centry_aentry(centry); aentry = mlxsw_sp_acl_tcam_centry_aentry(centry);
erp = mlxsw_sp_acl_erp_get(aregion, mask, true); erp_mask = mlxsw_sp_acl_erp_mask_get(aregion, mask, true);
if (IS_ERR(erp)) if (IS_ERR(erp_mask))
return PTR_ERR(erp); return PTR_ERR(erp_mask);
aentry->erp = erp; aentry->erp_mask = erp_mask;
return 0; return 0;
} }
...@@ -57,7 +57,7 @@ mlxsw_sp2_acl_ctcam_region_entry_remove(struct mlxsw_sp_acl_ctcam_region *cregio ...@@ -57,7 +57,7 @@ mlxsw_sp2_acl_ctcam_region_entry_remove(struct mlxsw_sp_acl_ctcam_region *cregio
aregion = mlxsw_sp_acl_tcam_cregion_aregion(cregion); aregion = mlxsw_sp_acl_tcam_cregion_aregion(cregion);
aentry = mlxsw_sp_acl_tcam_centry_aentry(centry); aentry = mlxsw_sp_acl_tcam_centry_aentry(centry);
mlxsw_sp_acl_erp_put(aregion, aentry->erp); mlxsw_sp_acl_erp_mask_put(aregion, aentry->erp_mask);
} }
static const struct mlxsw_sp_acl_ctcam_region_ops static const struct mlxsw_sp_acl_ctcam_region_ops
......
...@@ -14,8 +14,8 @@ ...@@ -14,8 +14,8 @@
#include "spectrum_acl_tcam.h" #include "spectrum_acl_tcam.h"
#include "core_acl_flex_keys.h" #include "core_acl_flex_keys.h"
#define MLXSW_SP_ACL_ATCAM_LKEY_ID_BLOCK_START 6 #define MLXSW_SP_ACL_ATCAM_LKEY_ID_BLOCK_CLEAR_START 0
#define MLXSW_SP_ACL_ATCAM_LKEY_ID_BLOCK_END 11 #define MLXSW_SP_ACL_ATCAM_LKEY_ID_BLOCK_CLEAR_END 5
struct mlxsw_sp_acl_atcam_lkey_id_ht_key { struct mlxsw_sp_acl_atcam_lkey_id_ht_key {
char enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* MSB blocks */ char enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* MSB blocks */
...@@ -34,7 +34,7 @@ struct mlxsw_sp_acl_atcam_region_ops { ...@@ -34,7 +34,7 @@ struct mlxsw_sp_acl_atcam_region_ops {
void (*fini)(struct mlxsw_sp_acl_atcam_region *aregion); void (*fini)(struct mlxsw_sp_acl_atcam_region *aregion);
struct mlxsw_sp_acl_atcam_lkey_id * struct mlxsw_sp_acl_atcam_lkey_id *
(*lkey_id_get)(struct mlxsw_sp_acl_atcam_region *aregion, (*lkey_id_get)(struct mlxsw_sp_acl_atcam_region *aregion,
struct mlxsw_sp_acl_rule_info *rulei, u8 erp_id); char *enc_key, u8 erp_id);
void (*lkey_id_put)(struct mlxsw_sp_acl_atcam_region *aregion, void (*lkey_id_put)(struct mlxsw_sp_acl_atcam_region *aregion,
struct mlxsw_sp_acl_atcam_lkey_id *lkey_id); struct mlxsw_sp_acl_atcam_lkey_id *lkey_id);
}; };
...@@ -64,7 +64,7 @@ static const struct rhashtable_params mlxsw_sp_acl_atcam_entries_ht_params = { ...@@ -64,7 +64,7 @@ static const struct rhashtable_params mlxsw_sp_acl_atcam_entries_ht_params = {
static bool static bool
mlxsw_sp_acl_atcam_is_centry(const struct mlxsw_sp_acl_atcam_entry *aentry) mlxsw_sp_acl_atcam_is_centry(const struct mlxsw_sp_acl_atcam_entry *aentry)
{ {
return mlxsw_sp_acl_erp_is_ctcam_erp(aentry->erp); return mlxsw_sp_acl_erp_mask_is_ctcam(aentry->erp_mask);
} }
static int static int
...@@ -90,8 +90,7 @@ mlxsw_sp_acl_atcam_region_generic_fini(struct mlxsw_sp_acl_atcam_region *aregion ...@@ -90,8 +90,7 @@ mlxsw_sp_acl_atcam_region_generic_fini(struct mlxsw_sp_acl_atcam_region *aregion
static struct mlxsw_sp_acl_atcam_lkey_id * static struct mlxsw_sp_acl_atcam_lkey_id *
mlxsw_sp_acl_atcam_generic_lkey_id_get(struct mlxsw_sp_acl_atcam_region *aregion, mlxsw_sp_acl_atcam_generic_lkey_id_get(struct mlxsw_sp_acl_atcam_region *aregion,
struct mlxsw_sp_acl_rule_info *rulei, char *enc_key, u8 erp_id)
u8 erp_id)
{ {
struct mlxsw_sp_acl_atcam_region_generic *region_generic; struct mlxsw_sp_acl_atcam_region_generic *region_generic;
...@@ -220,8 +219,7 @@ mlxsw_sp_acl_atcam_lkey_id_destroy(struct mlxsw_sp_acl_atcam_region *aregion, ...@@ -220,8 +219,7 @@ mlxsw_sp_acl_atcam_lkey_id_destroy(struct mlxsw_sp_acl_atcam_region *aregion,
static struct mlxsw_sp_acl_atcam_lkey_id * static struct mlxsw_sp_acl_atcam_lkey_id *
mlxsw_sp_acl_atcam_12kb_lkey_id_get(struct mlxsw_sp_acl_atcam_region *aregion, mlxsw_sp_acl_atcam_12kb_lkey_id_get(struct mlxsw_sp_acl_atcam_region *aregion,
struct mlxsw_sp_acl_rule_info *rulei, char *enc_key, u8 erp_id)
u8 erp_id)
{ {
struct mlxsw_sp_acl_atcam_region_12kb *region_12kb = aregion->priv; struct mlxsw_sp_acl_atcam_region_12kb *region_12kb = aregion->priv;
struct mlxsw_sp_acl_tcam_region *region = aregion->region; struct mlxsw_sp_acl_tcam_region *region = aregion->region;
...@@ -230,9 +228,10 @@ mlxsw_sp_acl_atcam_12kb_lkey_id_get(struct mlxsw_sp_acl_atcam_region *aregion, ...@@ -230,9 +228,10 @@ mlxsw_sp_acl_atcam_12kb_lkey_id_get(struct mlxsw_sp_acl_atcam_region *aregion,
struct mlxsw_afk *afk = mlxsw_sp_acl_afk(mlxsw_sp->acl); struct mlxsw_afk *afk = mlxsw_sp_acl_afk(mlxsw_sp->acl);
struct mlxsw_sp_acl_atcam_lkey_id *lkey_id; struct mlxsw_sp_acl_atcam_lkey_id *lkey_id;
mlxsw_afk_encode(afk, region->key_info, &rulei->values, ht_key.enc_key, memcpy(ht_key.enc_key, enc_key, sizeof(ht_key.enc_key));
NULL, MLXSW_SP_ACL_ATCAM_LKEY_ID_BLOCK_START, mlxsw_afk_clear(afk, ht_key.enc_key,
MLXSW_SP_ACL_ATCAM_LKEY_ID_BLOCK_END); MLXSW_SP_ACL_ATCAM_LKEY_ID_BLOCK_CLEAR_START,
MLXSW_SP_ACL_ATCAM_LKEY_ID_BLOCK_CLEAR_END);
ht_key.erp_id = erp_id; ht_key.erp_id = erp_id;
lkey_id = rhashtable_lookup_fast(&region_12kb->lkey_ht, &ht_key, lkey_id = rhashtable_lookup_fast(&region_12kb->lkey_ht, &ht_key,
mlxsw_sp_acl_atcam_lkey_id_ht_params); mlxsw_sp_acl_atcam_lkey_id_ht_params);
...@@ -379,7 +378,7 @@ mlxsw_sp_acl_atcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp, ...@@ -379,7 +378,7 @@ mlxsw_sp_acl_atcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_rule_info *rulei) struct mlxsw_sp_acl_rule_info *rulei)
{ {
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_id(aentry->erp); u8 erp_id = mlxsw_sp_acl_erp_mask_erp_id(aentry->erp_mask);
struct mlxsw_sp_acl_atcam_lkey_id *lkey_id; struct mlxsw_sp_acl_atcam_lkey_id *lkey_id;
char ptce3_pl[MLXSW_REG_PTCE3_LEN]; char ptce3_pl[MLXSW_REG_PTCE3_LEN];
u32 kvdl_index, priority; u32 kvdl_index, priority;
...@@ -389,7 +388,8 @@ mlxsw_sp_acl_atcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp, ...@@ -389,7 +388,8 @@ 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, rulei, erp_id); lkey_id = aregion->ops->lkey_id_get(aregion, aentry->ht_key.enc_key,
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;
...@@ -398,6 +398,9 @@ mlxsw_sp_acl_atcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp, ...@@ -398,6 +398,9 @@ mlxsw_sp_acl_atcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp,
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->ht_key.enc_key, erp_id,
aentry->delta_info.start,
aentry->delta_info.mask,
aentry->delta_info.value,
refcount_read(&lkey_id->refcnt) != 1, lkey_id->id, refcount_read(&lkey_id->refcnt) != 1, lkey_id->id,
kvdl_index); kvdl_index);
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce3), ptce3_pl); err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce3), ptce3_pl);
...@@ -418,12 +421,17 @@ mlxsw_sp_acl_atcam_region_entry_remove(struct mlxsw_sp *mlxsw_sp, ...@@ -418,12 +421,17 @@ 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_id(aentry->erp); 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, aentry->ht_key.enc_key, region->tcam_region_info,
erp_id, refcount_read(&lkey_id->refcnt) != 1, enc_key, erp_id,
aentry->delta_info.start,
aentry->delta_info.mask,
aentry->delta_info.value,
refcount_read(&lkey_id->refcnt) != 1,
lkey_id->id, 0); lkey_id->id, 0);
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce3), ptce3_pl); mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce3), ptce3_pl);
aregion->ops->lkey_id_put(aregion, lkey_id); aregion->ops->lkey_id_put(aregion, lkey_id);
...@@ -438,19 +446,30 @@ __mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp, ...@@ -438,19 +446,30 @@ __mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_tcam_region *region = aregion->region; struct mlxsw_sp_acl_tcam_region *region = aregion->region;
char mask[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN] = { 0 }; char mask[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN] = { 0 };
struct mlxsw_afk *afk = mlxsw_sp_acl_afk(mlxsw_sp->acl); struct mlxsw_afk *afk = mlxsw_sp_acl_afk(mlxsw_sp->acl);
struct mlxsw_sp_acl_erp *erp; const struct mlxsw_sp_acl_erp_delta *delta;
unsigned int blocks_count; struct mlxsw_sp_acl_erp_mask *erp_mask;
int err; int err;
blocks_count = mlxsw_afk_key_info_blocks_count_get(region->key_info);
mlxsw_afk_encode(afk, region->key_info, &rulei->values, mlxsw_afk_encode(afk, region->key_info, &rulei->values,
aentry->ht_key.enc_key, mask, 0, blocks_count - 1); aentry->full_enc_key, mask);
erp = mlxsw_sp_acl_erp_get(aregion, mask, false); erp_mask = mlxsw_sp_acl_erp_mask_get(aregion, mask, false);
if (IS_ERR(erp)) if (IS_ERR(erp_mask))
return PTR_ERR(erp); return PTR_ERR(erp_mask);
aentry->erp = erp; aentry->erp_mask = erp_mask;
aentry->ht_key.erp_id = mlxsw_sp_acl_erp_id(erp); aentry->ht_key.erp_id = mlxsw_sp_acl_erp_mask_erp_id(erp_mask);
memcpy(aentry->ht_key.enc_key, aentry->full_enc_key,
sizeof(aentry->ht_key.enc_key));
/* Compute all needed delta information and clear the delta bits
* from the encrypted key.
*/
delta = mlxsw_sp_acl_erp_delta(aentry->erp_mask);
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.value =
mlxsw_sp_acl_erp_delta_value(delta, aentry->full_enc_key);
mlxsw_sp_acl_erp_delta_clear(delta, aentry->ht_key.enc_key);
/* 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
...@@ -472,7 +491,7 @@ __mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp, ...@@ -472,7 +491,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:
mlxsw_sp_acl_erp_put(aregion, erp); mlxsw_sp_acl_erp_mask_put(aregion, erp_mask);
return err; return err;
} }
...@@ -484,7 +503,7 @@ __mlxsw_sp_acl_atcam_entry_del(struct mlxsw_sp *mlxsw_sp, ...@@ -484,7 +503,7 @@ __mlxsw_sp_acl_atcam_entry_del(struct mlxsw_sp *mlxsw_sp,
mlxsw_sp_acl_atcam_region_entry_remove(mlxsw_sp, aregion, aentry); mlxsw_sp_acl_atcam_region_entry_remove(mlxsw_sp, aregion, 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);
mlxsw_sp_acl_erp_put(aregion, aentry->erp); mlxsw_sp_acl_erp_mask_put(aregion, aentry->erp_mask);
} }
int mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp, int mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp,
......
...@@ -46,7 +46,6 @@ mlxsw_sp_acl_ctcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp, ...@@ -46,7 +46,6 @@ mlxsw_sp_acl_ctcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_tcam_region *region = cregion->region; struct mlxsw_sp_acl_tcam_region *region = cregion->region;
struct mlxsw_afk *afk = mlxsw_sp_acl_afk(mlxsw_sp->acl); struct mlxsw_afk *afk = mlxsw_sp_acl_afk(mlxsw_sp->acl);
char ptce2_pl[MLXSW_REG_PTCE2_LEN]; char ptce2_pl[MLXSW_REG_PTCE2_LEN];
unsigned int blocks_count;
char *act_set; char *act_set;
u32 priority; u32 priority;
char *mask; char *mask;
...@@ -63,9 +62,7 @@ mlxsw_sp_acl_ctcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp, ...@@ -63,9 +62,7 @@ mlxsw_sp_acl_ctcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp,
centry->parman_item.index, priority); centry->parman_item.index, priority);
key = mlxsw_reg_ptce2_flex_key_blocks_data(ptce2_pl); key = mlxsw_reg_ptce2_flex_key_blocks_data(ptce2_pl);
mask = mlxsw_reg_ptce2_mask_data(ptce2_pl); mask = mlxsw_reg_ptce2_mask_data(ptce2_pl);
blocks_count = mlxsw_afk_key_info_blocks_count_get(region->key_info); mlxsw_afk_encode(afk, region->key_info, &rulei->values, key, mask);
mlxsw_afk_encode(afk, region->key_info, &rulei->values, key, mask, 0,
blocks_count - 1);
err = cregion->ops->entry_insert(cregion, centry, mask); err = cregion->ops->entry_insert(cregion, centry, mask);
if (err) if (err)
......
...@@ -98,8 +98,8 @@ static const struct mlxsw_afk_block mlxsw_sp1_afk_blocks[] = { ...@@ -98,8 +98,8 @@ static const struct mlxsw_afk_block mlxsw_sp1_afk_blocks[] = {
#define MLXSW_SP1_AFK_KEY_BLOCK_SIZE 16 #define MLXSW_SP1_AFK_KEY_BLOCK_SIZE 16
static void mlxsw_sp1_afk_encode_block(char *block, int block_index, static void mlxsw_sp1_afk_encode_block(char *output, int block_index,
char *output) char *block)
{ {
unsigned int offset = block_index * MLXSW_SP1_AFK_KEY_BLOCK_SIZE; unsigned int offset = block_index * MLXSW_SP1_AFK_KEY_BLOCK_SIZE;
char *output_indexed = output + offset; char *output_indexed = output + offset;
...@@ -107,10 +107,19 @@ static void mlxsw_sp1_afk_encode_block(char *block, int block_index, ...@@ -107,10 +107,19 @@ static void mlxsw_sp1_afk_encode_block(char *block, int block_index,
memcpy(output_indexed, block, MLXSW_SP1_AFK_KEY_BLOCK_SIZE); memcpy(output_indexed, block, MLXSW_SP1_AFK_KEY_BLOCK_SIZE);
} }
static void mlxsw_sp1_afk_clear_block(char *output, int block_index)
{
unsigned int offset = block_index * MLXSW_SP1_AFK_KEY_BLOCK_SIZE;
char *output_indexed = output + offset;
memset(output_indexed, 0, MLXSW_SP1_AFK_KEY_BLOCK_SIZE);
}
const struct mlxsw_afk_ops mlxsw_sp1_afk_ops = { const struct mlxsw_afk_ops mlxsw_sp1_afk_ops = {
.blocks = mlxsw_sp1_afk_blocks, .blocks = mlxsw_sp1_afk_blocks,
.blocks_count = ARRAY_SIZE(mlxsw_sp1_afk_blocks), .blocks_count = ARRAY_SIZE(mlxsw_sp1_afk_blocks),
.encode_block = mlxsw_sp1_afk_encode_block, .encode_block = mlxsw_sp1_afk_encode_block,
.clear_block = mlxsw_sp1_afk_clear_block,
}; };
static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_0[] = { static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_0[] = {
...@@ -263,10 +272,9 @@ static const struct mlxsw_sp2_afk_block_layout mlxsw_sp2_afk_blocks_layout[] = { ...@@ -263,10 +272,9 @@ static const struct mlxsw_sp2_afk_block_layout mlxsw_sp2_afk_blocks_layout[] = {
MLXSW_SP2_AFK_BLOCK_LAYOUT(block11, 0x00, 12), MLXSW_SP2_AFK_BLOCK_LAYOUT(block11, 0x00, 12),
}; };
static void mlxsw_sp2_afk_encode_block(char *block, int block_index, static void __mlxsw_sp2_afk_block_value_set(char *output, int block_index,
char *output) u64 block_value)
{ {
u64 block_value = mlxsw_sp2_afk_block_value_get(block);
const struct mlxsw_sp2_afk_block_layout *block_layout; const struct mlxsw_sp2_afk_block_layout *block_layout;
if (WARN_ON(block_index < 0 || if (WARN_ON(block_index < 0 ||
...@@ -278,8 +286,22 @@ static void mlxsw_sp2_afk_encode_block(char *block, int block_index, ...@@ -278,8 +286,22 @@ static void mlxsw_sp2_afk_encode_block(char *block, int block_index,
&block_layout->item, 0, block_value); &block_layout->item, 0, block_value);
} }
static void mlxsw_sp2_afk_encode_block(char *output, int block_index,
char *block)
{
u64 block_value = mlxsw_sp2_afk_block_value_get(block);
__mlxsw_sp2_afk_block_value_set(output, block_index, block_value);
}
static void mlxsw_sp2_afk_clear_block(char *output, int block_index)
{
__mlxsw_sp2_afk_block_value_set(output, block_index, 0);
}
const struct mlxsw_afk_ops mlxsw_sp2_afk_ops = { const struct mlxsw_afk_ops mlxsw_sp2_afk_ops = {
.blocks = mlxsw_sp2_afk_blocks, .blocks = mlxsw_sp2_afk_blocks,
.blocks_count = ARRAY_SIZE(mlxsw_sp2_afk_blocks), .blocks_count = ARRAY_SIZE(mlxsw_sp2_afk_blocks),
.encode_block = mlxsw_sp2_afk_encode_block, .encode_block = mlxsw_sp2_afk_encode_block,
.clear_block = mlxsw_sp2_afk_clear_block,
}; };
...@@ -154,7 +154,9 @@ struct mlxsw_sp_acl_atcam_region { ...@@ -154,7 +154,9 @@ 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 enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded key,
* minus delta bits.
*/
u8 erp_id; u8 erp_id;
}; };
...@@ -165,9 +167,15 @@ struct mlxsw_sp_acl_atcam_chunk { ...@@ -165,9 +167,15 @@ 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 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 */
struct {
u16 start;
u8 mask;
u8 value;
} delta_info;
struct mlxsw_sp_acl_ctcam_entry centry; struct mlxsw_sp_acl_ctcam_entry centry;
struct mlxsw_sp_acl_atcam_lkey_id *lkey_id; struct mlxsw_sp_acl_atcam_lkey_id *lkey_id;
struct mlxsw_sp_acl_erp *erp; struct mlxsw_sp_acl_erp_mask *erp_mask;
}; };
static inline struct mlxsw_sp_acl_atcam_region * static inline struct mlxsw_sp_acl_atcam_region *
...@@ -209,15 +217,27 @@ int mlxsw_sp_acl_atcam_init(struct mlxsw_sp *mlxsw_sp, ...@@ -209,15 +217,27 @@ int mlxsw_sp_acl_atcam_init(struct mlxsw_sp *mlxsw_sp,
void mlxsw_sp_acl_atcam_fini(struct mlxsw_sp *mlxsw_sp, void mlxsw_sp_acl_atcam_fini(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_atcam *atcam); struct mlxsw_sp_acl_atcam *atcam);
struct mlxsw_sp_acl_erp; struct mlxsw_sp_acl_erp_delta;
bool mlxsw_sp_acl_erp_is_ctcam_erp(const struct mlxsw_sp_acl_erp *erp); u16 mlxsw_sp_acl_erp_delta_start(const struct mlxsw_sp_acl_erp_delta *delta);
u8 mlxsw_sp_acl_erp_id(const struct mlxsw_sp_acl_erp *erp); u8 mlxsw_sp_acl_erp_delta_mask(const struct mlxsw_sp_acl_erp_delta *delta);
struct mlxsw_sp_acl_erp * u8 mlxsw_sp_acl_erp_delta_value(const struct mlxsw_sp_acl_erp_delta *delta,
mlxsw_sp_acl_erp_get(struct mlxsw_sp_acl_atcam_region *aregion, 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); const char *mask, bool ctcam);
void mlxsw_sp_acl_erp_put(struct mlxsw_sp_acl_atcam_region *aregion, void mlxsw_sp_acl_erp_mask_put(struct mlxsw_sp_acl_atcam_region *aregion,
struct mlxsw_sp_acl_erp *erp); struct mlxsw_sp_acl_erp_mask *erp_mask);
int mlxsw_sp_acl_erp_region_init(struct mlxsw_sp_acl_atcam_region *aregion); 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); 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, int mlxsw_sp_acl_erps_init(struct mlxsw_sp *mlxsw_sp,
......
/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
/* Copyright (c) 2018 Mellanox Technologies. All rights reserved */
#ifndef _OBJAGG_H
#define _OBJAGG_H
struct objagg_ops {
size_t obj_size;
void * (*delta_create)(void *priv, void *parent_obj, void *obj);
void (*delta_destroy)(void *priv, void *delta_priv);
void * (*root_create)(void *priv, void *obj);
void (*root_destroy)(void *priv, void *root_priv);
};
struct objagg;
struct objagg_obj;
const void *objagg_obj_root_priv(const struct objagg_obj *objagg_obj);
const void *objagg_obj_delta_priv(const struct objagg_obj *objagg_obj);
const void *objagg_obj_raw(const struct objagg_obj *objagg_obj);
struct objagg_obj *objagg_obj_get(struct objagg *objagg, void *obj);
void objagg_obj_put(struct objagg *objagg, struct objagg_obj *objagg_obj);
struct objagg *objagg_create(const struct objagg_ops *ops, void *priv);
void objagg_destroy(struct objagg *objagg);
struct objagg_obj_stats {
unsigned int user_count;
unsigned int delta_user_count; /* includes delta object users */
};
struct objagg_obj_stats_info {
struct objagg_obj_stats stats;
struct objagg_obj *objagg_obj; /* associated object */
bool is_root;
};
struct objagg_stats {
unsigned int stats_info_count;
struct objagg_obj_stats_info stats_info[];
};
const struct objagg_stats *objagg_stats_get(struct objagg *objagg);
void objagg_stats_put(const struct objagg_stats *objagg_stats);
#endif
/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
/* Copyright (c) 2018 Mellanox Technologies. All rights reserved */
#undef TRACE_SYSTEM
#define TRACE_SYSTEM objagg
#if !defined(__TRACE_OBJAGG_H) || defined(TRACE_HEADER_MULTI_READ)
#define __TRACE_OBJAGG_H
#include <linux/tracepoint.h>
struct objagg;
struct objagg_obj;
TRACE_EVENT(objagg_create,
TP_PROTO(const struct objagg *objagg),
TP_ARGS(objagg),
TP_STRUCT__entry(
__field(const void *, objagg)
),
TP_fast_assign(
__entry->objagg = objagg;
),
TP_printk("objagg %p", __entry->objagg)
);
TRACE_EVENT(objagg_destroy,
TP_PROTO(const struct objagg *objagg),
TP_ARGS(objagg),
TP_STRUCT__entry(
__field(const void *, objagg)
),
TP_fast_assign(
__entry->objagg = objagg;
),
TP_printk("objagg %p", __entry->objagg)
);
TRACE_EVENT(objagg_obj_create,
TP_PROTO(const struct objagg *objagg,
const struct objagg_obj *obj),
TP_ARGS(objagg, obj),
TP_STRUCT__entry(
__field(const void *, objagg)
__field(const void *, obj)
),
TP_fast_assign(
__entry->objagg = objagg;
__entry->obj = obj;
),
TP_printk("objagg %p, obj %p", __entry->objagg, __entry->obj)
);
TRACE_EVENT(objagg_obj_destroy,
TP_PROTO(const struct objagg *objagg,
const struct objagg_obj *obj),
TP_ARGS(objagg, obj),
TP_STRUCT__entry(
__field(const void *, objagg)
__field(const void *, obj)
),
TP_fast_assign(
__entry->objagg = objagg;
__entry->obj = obj;
),
TP_printk("objagg %p, obj %p", __entry->objagg, __entry->obj)
);
TRACE_EVENT(objagg_obj_get,
TP_PROTO(const struct objagg *objagg,
const struct objagg_obj *obj,
unsigned int refcount),
TP_ARGS(objagg, obj, refcount),
TP_STRUCT__entry(
__field(const void *, objagg)
__field(const void *, obj)
__field(unsigned int, refcount)
),
TP_fast_assign(
__entry->objagg = objagg;
__entry->obj = obj;
__entry->refcount = refcount;
),
TP_printk("objagg %p, obj %p, refcount %u",
__entry->objagg, __entry->obj, __entry->refcount)
);
TRACE_EVENT(objagg_obj_put,
TP_PROTO(const struct objagg *objagg,
const struct objagg_obj *obj,
unsigned int refcount),
TP_ARGS(objagg, obj, refcount),
TP_STRUCT__entry(
__field(const void *, objagg)
__field(const void *, obj)
__field(unsigned int, refcount)
),
TP_fast_assign(
__entry->objagg = objagg;
__entry->obj = obj;
__entry->refcount = refcount;
),
TP_printk("objagg %p, obj %p, refcount %u",
__entry->objagg, __entry->obj, __entry->refcount)
);
TRACE_EVENT(objagg_obj_parent_assign,
TP_PROTO(const struct objagg *objagg,
const struct objagg_obj *obj,
const struct objagg_obj *parent,
unsigned int parent_refcount),
TP_ARGS(objagg, obj, parent, parent_refcount),
TP_STRUCT__entry(
__field(const void *, objagg)
__field(const void *, obj)
__field(const void *, parent)
__field(unsigned int, parent_refcount)
),
TP_fast_assign(
__entry->objagg = objagg;
__entry->obj = obj;
__entry->parent = parent;
__entry->parent_refcount = parent_refcount;
),
TP_printk("objagg %p, obj %p, parent %p, parent_refcount %u",
__entry->objagg, __entry->obj,
__entry->parent, __entry->parent_refcount)
);
TRACE_EVENT(objagg_obj_parent_unassign,
TP_PROTO(const struct objagg *objagg,
const struct objagg_obj *obj,
const struct objagg_obj *parent,
unsigned int parent_refcount),
TP_ARGS(objagg, obj, parent, parent_refcount),
TP_STRUCT__entry(
__field(const void *, objagg)
__field(const void *, obj)
__field(const void *, parent)
__field(unsigned int, parent_refcount)
),
TP_fast_assign(
__entry->objagg = objagg;
__entry->obj = obj;
__entry->parent = parent;
__entry->parent_refcount = parent_refcount;
),
TP_printk("objagg %p, obj %p, parent %p, parent_refcount %u",
__entry->objagg, __entry->obj,
__entry->parent, __entry->parent_refcount)
);
TRACE_EVENT(objagg_obj_root_create,
TP_PROTO(const struct objagg *objagg,
const struct objagg_obj *obj),
TP_ARGS(objagg, obj),
TP_STRUCT__entry(
__field(const void *, objagg)
__field(const void *, obj)
),
TP_fast_assign(
__entry->objagg = objagg;
__entry->obj = obj;
),
TP_printk("objagg %p, obj %p",
__entry->objagg, __entry->obj)
);
TRACE_EVENT(objagg_obj_root_destroy,
TP_PROTO(const struct objagg *objagg,
const struct objagg_obj *obj),
TP_ARGS(objagg, obj),
TP_STRUCT__entry(
__field(const void *, objagg)
__field(const void *, obj)
),
TP_fast_assign(
__entry->objagg = objagg;
__entry->obj = obj;
),
TP_printk("objagg %p, obj %p",
__entry->objagg, __entry->obj)
);
#endif /* __TRACE_OBJAGG_H */
/* This part must be outside protection */
#include <trace/define_trace.h>
...@@ -624,3 +624,6 @@ config GENERIC_LIB_CMPDI2 ...@@ -624,3 +624,6 @@ config GENERIC_LIB_CMPDI2
config GENERIC_LIB_UCMPDI2 config GENERIC_LIB_UCMPDI2
bool bool
config OBJAGG
tristate "objagg" if COMPILE_TEST
...@@ -1976,6 +1976,16 @@ config TEST_MEMCAT_P ...@@ -1976,6 +1976,16 @@ config TEST_MEMCAT_P
If unsure, say N. If unsure, say N.
config TEST_OBJAGG
tristate "Perform selftest on object aggreration manager"
default n
depends on OBJAGG
help
Enable this option to test object aggregation manager on boot
(or module load).
If unsure, say N.
endif # RUNTIME_TESTING_MENU endif # RUNTIME_TESTING_MENU
config MEMTEST config MEMTEST
......
...@@ -75,6 +75,7 @@ obj-$(CONFIG_TEST_PARMAN) += test_parman.o ...@@ -75,6 +75,7 @@ obj-$(CONFIG_TEST_PARMAN) += test_parman.o
obj-$(CONFIG_TEST_KMOD) += test_kmod.o obj-$(CONFIG_TEST_KMOD) += test_kmod.o
obj-$(CONFIG_TEST_DEBUG_VIRTUAL) += test_debug_virtual.o obj-$(CONFIG_TEST_DEBUG_VIRTUAL) += test_debug_virtual.o
obj-$(CONFIG_TEST_MEMCAT_P) += test_memcat_p.o obj-$(CONFIG_TEST_MEMCAT_P) += test_memcat_p.o
obj-$(CONFIG_TEST_OBJAGG) += test_objagg.o
ifeq ($(CONFIG_DEBUG_KOBJECT),y) ifeq ($(CONFIG_DEBUG_KOBJECT),y)
CFLAGS_kobject.o += -DDEBUG CFLAGS_kobject.o += -DDEBUG
...@@ -274,3 +275,4 @@ obj-$(CONFIG_GENERIC_LIB_LSHRDI3) += lshrdi3.o ...@@ -274,3 +275,4 @@ obj-$(CONFIG_GENERIC_LIB_LSHRDI3) += lshrdi3.o
obj-$(CONFIG_GENERIC_LIB_MULDI3) += muldi3.o obj-$(CONFIG_GENERIC_LIB_MULDI3) += muldi3.o
obj-$(CONFIG_GENERIC_LIB_CMPDI2) += cmpdi2.o obj-$(CONFIG_GENERIC_LIB_CMPDI2) += cmpdi2.o
obj-$(CONFIG_GENERIC_LIB_UCMPDI2) += ucmpdi2.o obj-$(CONFIG_GENERIC_LIB_UCMPDI2) += ucmpdi2.o
obj-$(CONFIG_OBJAGG) += objagg.o
This diff is collapsed.
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
lib_dir=$(dirname $0)/../../../../net/forwarding lib_dir=$(dirname $0)/../../../../net/forwarding
ALL_TESTS="single_mask_test identical_filters_test two_masks_test \ ALL_TESTS="single_mask_test identical_filters_test two_masks_test \
multiple_masks_test ctcam_edge_cases_test" multiple_masks_test ctcam_edge_cases_test delta_simple_test"
NUM_NETIFS=2 NUM_NETIFS=2
source $lib_dir/tc_common.sh source $lib_dir/tc_common.sh
source $lib_dir/lib.sh source $lib_dir/lib.sh
...@@ -142,7 +142,7 @@ two_masks_test() ...@@ -142,7 +142,7 @@ two_masks_test()
tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \ tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \
$tcflags dst_ip 192.0.2.2 action drop $tcflags dst_ip 192.0.2.2 action drop
tc filter add dev $h2 ingress protocol ip pref 3 handle 103 flower \ tc filter add dev $h2 ingress protocol ip pref 3 handle 103 flower \
$tcflags dst_ip 192.0.0.0/16 action drop $tcflags dst_ip 192.0.0.0/8 action drop
$MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
-t ip -q -t ip -q
...@@ -235,7 +235,7 @@ ctcam_two_atcam_masks_test() ...@@ -235,7 +235,7 @@ ctcam_two_atcam_masks_test()
$tcflags dst_ip 192.0.2.2 action drop $tcflags dst_ip 192.0.2.2 action drop
# Filter goes into A-TCAM # Filter goes into A-TCAM
tc filter add dev $h2 ingress protocol ip pref 3 handle 103 flower \ tc filter add dev $h2 ingress protocol ip pref 3 handle 103 flower \
$tcflags dst_ip 192.0.2.0/24 action drop $tcflags dst_ip 192.0.0.0/16 action drop
$MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \ $MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
-t ip -q -t ip -q
...@@ -324,6 +324,86 @@ ctcam_edge_cases_test() ...@@ -324,6 +324,86 @@ ctcam_edge_cases_test()
ctcam_no_atcam_masks_test ctcam_no_atcam_masks_test
} }
tp_record()
{
local tracepoint=$1
local cmd=$2
perf record -q -e $tracepoint $cmd
return $?
}
tp_check_hits()
{
local tracepoint=$1
local count=$2
perf_output=`perf script -F trace:event,trace`
hits=`echo $perf_output | grep "$tracepoint:" | wc -l`
if [[ "$count" -ne "$hits" ]]; then
return 1
fi
return 0
}
delta_simple_test()
{
# The first filter will create eRP, the second filter will fit into
# the first eRP with delta. Remove the first rule then and check that
# the eRP stays (referenced by the second filter).
RET=0
if [[ "$tcflags" != "skip_sw" ]]; then
return 0;
fi
tp_record "objagg:*" "tc filter add dev $h2 ingress protocol ip \
pref 1 handle 101 flower $tcflags dst_ip 192.0.0.0/24 \
action drop"
tp_check_hits "objagg:objagg_obj_root_create" 1
check_err $? "eRP was not created"
tp_record "objagg:*" "tc filter add dev $h2 ingress protocol ip \
pref 2 handle 102 flower $tcflags dst_ip 192.0.2.2 \
action drop"
tp_check_hits "objagg:objagg_obj_root_create" 0
check_err $? "eRP was incorrectly created"
tp_check_hits "objagg:objagg_obj_parent_assign" 1
check_err $? "delta was not created"
$MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
-t ip -q
tc_check_packets "dev $h2 ingress" 101 1
check_fail $? "Matched a wrong filter"
tc_check_packets "dev $h2 ingress" 102 1
check_err $? "Did not match on correct filter"
tp_record "objagg:*" "tc filter del dev $h2 ingress protocol ip \
pref 1 handle 101 flower"
tp_check_hits "objagg:objagg_obj_root_destroy" 0
check_err $? "eRP was incorrectly destroyed"
tp_check_hits "objagg:objagg_obj_parent_unassign" 0
check_err $? "delta was incorrectly destroyed"
$MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
-t ip -q
tc_check_packets "dev $h2 ingress" 102 2
check_err $? "Did not match on correct filter after the first was removed"
tp_record "objagg:*" "tc filter del dev $h2 ingress protocol ip \
pref 2 handle 102 flower"
tp_check_hits "objagg:objagg_obj_parent_unassign" 1
check_err $? "delta was not destroyed"
tp_check_hits "objagg:objagg_obj_root_destroy" 1
check_err $? "eRP was not destroyed"
log_test "delta simple test ($tcflags)"
}
setup_prepare() setup_prepare()
{ {
h1=${NETIFS[p1]} h1=${NETIFS[p1]}
......
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