mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
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: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -10679,6 +10679,14 @@ L: linux-nfc@lists.01.org (moderated for non-subscribers)
|
||||
S: Supported
|
||||
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
|
||||
M: Josh Poimboeuf <jpoimboe@redhat.com>
|
||||
M: Peter Zijlstra <peterz@infradead.org>
|
||||
|
||||
@@ -80,6 +80,7 @@ config MLXSW_SPECTRUM
|
||||
depends on IPV6_GRE || IPV6_GRE=n
|
||||
select GENERIC_ALLOCATOR
|
||||
select PARMAN
|
||||
select OBJAGG
|
||||
select MLXFW
|
||||
default m
|
||||
---help---
|
||||
|
||||
@@ -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,
|
||||
struct mlxsw_afk_key_info *key_info,
|
||||
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_key[MLXSW_SP_AFK_KEY_BLOCK_MAX_SIZE];
|
||||
const struct mlxsw_afk_element_inst *elinst;
|
||||
enum mlxsw_afk_element element;
|
||||
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_mask, 0, MLXSW_SP_AFK_KEY_BLOCK_MAX_SIZE);
|
||||
|
||||
@@ -451,10 +453,18 @@ void mlxsw_afk_encode(struct mlxsw_afk *mlxsw_afk,
|
||||
values->storage.mask);
|
||||
}
|
||||
|
||||
if (key)
|
||||
mlxsw_afk->ops->encode_block(block_key, i, key);
|
||||
if (mask)
|
||||
mlxsw_afk->ops->encode_block(block_mask, i, mask);
|
||||
mlxsw_afk->ops->encode_block(key, i, block_key);
|
||||
mlxsw_afk->ops->encode_block(mask, i, block_mask);
|
||||
}
|
||||
}
|
||||
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;
|
||||
struct mlxsw_afk_ops {
|
||||
const struct mlxsw_afk_block *blocks;
|
||||
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,
|
||||
@@ -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,
|
||||
struct mlxsw_afk_key_info *key_info,
|
||||
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
|
||||
|
||||
@@ -2834,8 +2834,9 @@ static inline void mlxsw_reg_ptce3_pack(char *payload, bool valid,
|
||||
u32 priority,
|
||||
const char *tcam_region_info,
|
||||
const char *key, u8 erp_id,
|
||||
bool large_exists, u32 lkey_id,
|
||||
u32 action_pointer)
|
||||
u16 delta_start, u8 delta_mask,
|
||||
u8 delta_value, bool large_exists,
|
||||
u32 lkey_id, u32 action_pointer)
|
||||
{
|
||||
MLXSW_REG_ZERO(ptce3, payload);
|
||||
mlxsw_reg_ptce3_v_set(payload, 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_flex2_key_blocks_memcpy_to(payload, key);
|
||||
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_entry_key_id_set(payload, lkey_id);
|
||||
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
|
||||
{
|
||||
struct mlxsw_sp_acl_atcam_region *aregion;
|
||||
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);
|
||||
aentry = mlxsw_sp_acl_tcam_centry_aentry(centry);
|
||||
|
||||
erp = mlxsw_sp_acl_erp_get(aregion, mask, true);
|
||||
if (IS_ERR(erp))
|
||||
return PTR_ERR(erp);
|
||||
aentry->erp = erp;
|
||||
erp_mask = mlxsw_sp_acl_erp_mask_get(aregion, mask, true);
|
||||
if (IS_ERR(erp_mask))
|
||||
return PTR_ERR(erp_mask);
|
||||
aentry->erp_mask = erp_mask;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -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);
|
||||
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
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
#include "spectrum_acl_tcam.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_END 11
|
||||
#define MLXSW_SP_ACL_ATCAM_LKEY_ID_BLOCK_CLEAR_START 0
|
||||
#define MLXSW_SP_ACL_ATCAM_LKEY_ID_BLOCK_CLEAR_END 5
|
||||
|
||||
struct mlxsw_sp_acl_atcam_lkey_id_ht_key {
|
||||
char enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* MSB blocks */
|
||||
@@ -34,7 +34,7 @@ struct mlxsw_sp_acl_atcam_region_ops {
|
||||
void (*fini)(struct mlxsw_sp_acl_atcam_region *aregion);
|
||||
struct mlxsw_sp_acl_atcam_lkey_id *
|
||||
(*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,
|
||||
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 = {
|
||||
static bool
|
||||
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
|
||||
@@ -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 *
|
||||
mlxsw_sp_acl_atcam_generic_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)
|
||||
{
|
||||
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,
|
||||
|
||||
static struct mlxsw_sp_acl_atcam_lkey_id *
|
||||
mlxsw_sp_acl_atcam_12kb_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)
|
||||
{
|
||||
struct mlxsw_sp_acl_atcam_region_12kb *region_12kb = aregion->priv;
|
||||
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,
|
||||
struct mlxsw_afk *afk = mlxsw_sp_acl_afk(mlxsw_sp->acl);
|
||||
struct mlxsw_sp_acl_atcam_lkey_id *lkey_id;
|
||||
|
||||
mlxsw_afk_encode(afk, region->key_info, &rulei->values, ht_key.enc_key,
|
||||
NULL, MLXSW_SP_ACL_ATCAM_LKEY_ID_BLOCK_START,
|
||||
MLXSW_SP_ACL_ATCAM_LKEY_ID_BLOCK_END);
|
||||
memcpy(ht_key.enc_key, enc_key, sizeof(ht_key.enc_key));
|
||||
mlxsw_afk_clear(afk, ht_key.enc_key,
|
||||
MLXSW_SP_ACL_ATCAM_LKEY_ID_BLOCK_CLEAR_START,
|
||||
MLXSW_SP_ACL_ATCAM_LKEY_ID_BLOCK_CLEAR_END);
|
||||
ht_key.erp_id = erp_id;
|
||||
lkey_id = rhashtable_lookup_fast(®ion_12kb->lkey_ht, &ht_key,
|
||||
mlxsw_sp_acl_atcam_lkey_id_ht_params);
|
||||
@@ -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_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;
|
||||
char ptce3_pl[MLXSW_REG_PTCE3_LEN];
|
||||
u32 kvdl_index, priority;
|
||||
@@ -389,7 +388,8 @@ mlxsw_sp_acl_atcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp,
|
||||
if (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))
|
||||
return PTR_ERR(lkey_id);
|
||||
aentry->lkey_id = lkey_id;
|
||||
@@ -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,
|
||||
priority, region->tcam_region_info,
|
||||
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,
|
||||
kvdl_index);
|
||||
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,
|
||||
{
|
||||
struct mlxsw_sp_acl_atcam_lkey_id *lkey_id = aentry->lkey_id;
|
||||
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];
|
||||
|
||||
mlxsw_reg_ptce3_pack(ptce3_pl, false, MLXSW_REG_PTCE3_OP_WRITE_WRITE, 0,
|
||||
region->tcam_region_info, aentry->ht_key.enc_key,
|
||||
erp_id, refcount_read(&lkey_id->refcnt) != 1,
|
||||
region->tcam_region_info,
|
||||
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);
|
||||
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce3), ptce3_pl);
|
||||
aregion->ops->lkey_id_put(aregion, lkey_id);
|
||||
@@ -438,19 +446,30 @@ __mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_acl_tcam_region *region = aregion->region;
|
||||
char mask[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN] = { 0 };
|
||||
struct mlxsw_afk *afk = mlxsw_sp_acl_afk(mlxsw_sp->acl);
|
||||
struct mlxsw_sp_acl_erp *erp;
|
||||
unsigned int blocks_count;
|
||||
const struct mlxsw_sp_acl_erp_delta *delta;
|
||||
struct mlxsw_sp_acl_erp_mask *erp_mask;
|
||||
int err;
|
||||
|
||||
blocks_count = mlxsw_afk_key_info_blocks_count_get(region->key_info);
|
||||
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);
|
||||
if (IS_ERR(erp))
|
||||
return PTR_ERR(erp);
|
||||
aentry->erp = erp;
|
||||
aentry->ht_key.erp_id = mlxsw_sp_acl_erp_id(erp);
|
||||
erp_mask = mlxsw_sp_acl_erp_mask_get(aregion, mask, false);
|
||||
if (IS_ERR(erp_mask))
|
||||
return PTR_ERR(erp_mask);
|
||||
aentry->erp_mask = 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,
|
||||
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
|
||||
* let the rule spill into C-TCAM
|
||||
@@ -472,7 +491,7 @@ err_rule_insert:
|
||||
rhashtable_remove_fast(&aregion->entries_ht, &aentry->ht_node,
|
||||
mlxsw_sp_acl_atcam_entries_ht_params);
|
||||
err_rhashtable_insert:
|
||||
mlxsw_sp_acl_erp_put(aregion, erp);
|
||||
mlxsw_sp_acl_erp_mask_put(aregion, erp_mask);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
rhashtable_remove_fast(&aregion->entries_ht, &aentry->ht_node,
|
||||
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,
|
||||
|
||||
@@ -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_afk *afk = mlxsw_sp_acl_afk(mlxsw_sp->acl);
|
||||
char ptce2_pl[MLXSW_REG_PTCE2_LEN];
|
||||
unsigned int blocks_count;
|
||||
char *act_set;
|
||||
u32 priority;
|
||||
char *mask;
|
||||
@@ -63,9 +62,7 @@ mlxsw_sp_acl_ctcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp,
|
||||
centry->parman_item.index, priority);
|
||||
key = mlxsw_reg_ptce2_flex_key_blocks_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, 0,
|
||||
blocks_count - 1);
|
||||
mlxsw_afk_encode(afk, region->key_info, &rulei->values, key, mask);
|
||||
|
||||
err = cregion->ops->entry_insert(cregion, centry, mask);
|
||||
if (err)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -98,8 +98,8 @@ static const struct mlxsw_afk_block mlxsw_sp1_afk_blocks[] = {
|
||||
|
||||
#define MLXSW_SP1_AFK_KEY_BLOCK_SIZE 16
|
||||
|
||||
static void mlxsw_sp1_afk_encode_block(char *block, int block_index,
|
||||
char *output)
|
||||
static void mlxsw_sp1_afk_encode_block(char *output, int block_index,
|
||||
char *block)
|
||||
{
|
||||
unsigned int offset = block_index * MLXSW_SP1_AFK_KEY_BLOCK_SIZE;
|
||||
char *output_indexed = output + offset;
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
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 = {
|
||||
.blocks = mlxsw_sp1_afk_blocks,
|
||||
.blocks_count = ARRAY_SIZE(mlxsw_sp1_afk_blocks),
|
||||
.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[] = {
|
||||
@@ -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),
|
||||
};
|
||||
|
||||
static void mlxsw_sp2_afk_encode_block(char *block, int block_index,
|
||||
char *output)
|
||||
static void __mlxsw_sp2_afk_block_value_set(char *output, int block_index,
|
||||
u64 block_value)
|
||||
{
|
||||
u64 block_value = mlxsw_sp2_afk_block_value_get(block);
|
||||
const struct mlxsw_sp2_afk_block_layout *block_layout;
|
||||
|
||||
if (WARN_ON(block_index < 0 ||
|
||||
@@ -278,8 +286,22 @@ static void mlxsw_sp2_afk_encode_block(char *block, int block_index,
|
||||
&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 = {
|
||||
.blocks = mlxsw_sp2_afk_blocks,
|
||||
.blocks_count = ARRAY_SIZE(mlxsw_sp2_afk_blocks),
|
||||
.encode_block = mlxsw_sp2_afk_encode_block,
|
||||
.clear_block = mlxsw_sp2_afk_clear_block,
|
||||
};
|
||||
|
||||
@@ -154,7 +154,9 @@ struct mlxsw_sp_acl_atcam_region {
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
@@ -165,9 +167,15 @@ struct mlxsw_sp_acl_atcam_chunk {
|
||||
struct mlxsw_sp_acl_atcam_entry {
|
||||
struct rhash_head ht_node;
|
||||
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_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 *
|
||||
@@ -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,
|
||||
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);
|
||||
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,
|
||||
const char *mask, bool ctcam);
|
||||
void mlxsw_sp_acl_erp_put(struct mlxsw_sp_acl_atcam_region *aregion,
|
||||
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_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_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,
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/* 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
|
||||
@@ -0,0 +1,228 @@
|
||||
/* 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
|
||||
|
||||
config GENERIC_LIB_UCMPDI2
|
||||
bool
|
||||
|
||||
config OBJAGG
|
||||
tristate "objagg" if COMPILE_TEST
|
||||
|
||||
@@ -1976,6 +1976,16 @@ config TEST_MEMCAT_P
|
||||
|
||||
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
|
||||
|
||||
config MEMTEST
|
||||
|
||||
@@ -75,6 +75,7 @@ obj-$(CONFIG_TEST_PARMAN) += test_parman.o
|
||||
obj-$(CONFIG_TEST_KMOD) += test_kmod.o
|
||||
obj-$(CONFIG_TEST_DEBUG_VIRTUAL) += test_debug_virtual.o
|
||||
obj-$(CONFIG_TEST_MEMCAT_P) += test_memcat_p.o
|
||||
obj-$(CONFIG_TEST_OBJAGG) += test_objagg.o
|
||||
|
||||
ifeq ($(CONFIG_DEBUG_KOBJECT),y)
|
||||
CFLAGS_kobject.o += -DDEBUG
|
||||
@@ -274,3 +275,4 @@ obj-$(CONFIG_GENERIC_LIB_LSHRDI3) += lshrdi3.o
|
||||
obj-$(CONFIG_GENERIC_LIB_MULDI3) += muldi3.o
|
||||
obj-$(CONFIG_GENERIC_LIB_CMPDI2) += cmpdi2.o
|
||||
obj-$(CONFIG_GENERIC_LIB_UCMPDI2) += ucmpdi2.o
|
||||
obj-$(CONFIG_OBJAGG) += objagg.o
|
||||
|
||||
+501
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@
|
||||
lib_dir=$(dirname $0)/../../../../net/forwarding
|
||||
|
||||
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
|
||||
source $lib_dir/tc_common.sh
|
||||
source $lib_dir/lib.sh
|
||||
@@ -142,7 +142,7 @@ two_masks_test()
|
||||
tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \
|
||||
$tcflags dst_ip 192.0.2.2 action drop
|
||||
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 \
|
||||
-t ip -q
|
||||
@@ -235,7 +235,7 @@ ctcam_two_atcam_masks_test()
|
||||
$tcflags dst_ip 192.0.2.2 action drop
|
||||
# Filter goes into A-TCAM
|
||||
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 \
|
||||
-t ip -q
|
||||
@@ -324,6 +324,86 @@ ctcam_edge_cases_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()
|
||||
{
|
||||
h1=${NETIFS[p1]}
|
||||
|
||||
Reference in New Issue
Block a user