Skip to content

Commit c22291f

Browse files
jpirkodavem330
authored andcommitted
mlxsw: spectrum: acl: Implement delta for ERP
Allow ERP sharing for multiple mask. Do it by properly implementing delta_create() objagg object. Use the computed delta info for inserting rules in A-TCAM. Signed-off-by: Jiri Pirko <[email protected]> Signed-off-by: Ido Schimmel <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent c293ba3 commit c22291f

File tree

4 files changed

+237
-12
lines changed

4 files changed

+237
-12
lines changed

drivers/net/ethernet/mellanox/mlxsw/reg.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2834,8 +2834,9 @@ static inline void mlxsw_reg_ptce3_pack(char *payload, bool valid,
28342834
u32 priority,
28352835
const char *tcam_region_info,
28362836
const char *key, u8 erp_id,
2837-
bool large_exists, u32 lkey_id,
2838-
u32 action_pointer)
2837+
u16 delta_start, u8 delta_mask,
2838+
u8 delta_value, bool large_exists,
2839+
u32 lkey_id, u32 action_pointer)
28392840
{
28402841
MLXSW_REG_ZERO(ptce3, payload);
28412842
mlxsw_reg_ptce3_v_set(payload, valid);
@@ -2844,6 +2845,9 @@ static inline void mlxsw_reg_ptce3_pack(char *payload, bool valid,
28442845
mlxsw_reg_ptce3_tcam_region_info_memcpy_to(payload, tcam_region_info);
28452846
mlxsw_reg_ptce3_flex2_key_blocks_memcpy_to(payload, key);
28462847
mlxsw_reg_ptce3_erp_id_set(payload, erp_id);
2848+
mlxsw_reg_ptce3_delta_start_set(payload, delta_start);
2849+
mlxsw_reg_ptce3_delta_mask_set(payload, delta_mask);
2850+
mlxsw_reg_ptce3_delta_value_set(payload, delta_value);
28472851
mlxsw_reg_ptce3_large_exists_set(payload, large_exists);
28482852
mlxsw_reg_ptce3_large_entry_key_id_set(payload, lkey_id);
28492853
mlxsw_reg_ptce3_action_pointer_set(payload, action_pointer);

drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_atcam.c

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,9 @@ mlxsw_sp_acl_atcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp,
398398
mlxsw_reg_ptce3_pack(ptce3_pl, true, MLXSW_REG_PTCE3_OP_WRITE_WRITE,
399399
priority, region->tcam_region_info,
400400
aentry->ht_key.enc_key, erp_id,
401+
aentry->delta_info.start,
402+
aentry->delta_info.mask,
403+
aentry->delta_info.value,
401404
refcount_read(&lkey_id->refcnt) != 1, lkey_id->id,
402405
kvdl_index);
403406
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce3), ptce3_pl);
@@ -419,11 +422,16 @@ mlxsw_sp_acl_atcam_region_entry_remove(struct mlxsw_sp *mlxsw_sp,
419422
struct mlxsw_sp_acl_atcam_lkey_id *lkey_id = aentry->lkey_id;
420423
struct mlxsw_sp_acl_tcam_region *region = aregion->region;
421424
u8 erp_id = mlxsw_sp_acl_erp_mask_erp_id(aentry->erp_mask);
425+
char *enc_key = aentry->ht_key.enc_key;
422426
char ptce3_pl[MLXSW_REG_PTCE3_LEN];
423427

424428
mlxsw_reg_ptce3_pack(ptce3_pl, false, MLXSW_REG_PTCE3_OP_WRITE_WRITE, 0,
425-
region->tcam_region_info, aentry->ht_key.enc_key,
426-
erp_id, refcount_read(&lkey_id->refcnt) != 1,
429+
region->tcam_region_info,
430+
enc_key, erp_id,
431+
aentry->delta_info.start,
432+
aentry->delta_info.mask,
433+
aentry->delta_info.value,
434+
refcount_read(&lkey_id->refcnt) != 1,
427435
lkey_id->id, 0);
428436
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce3), ptce3_pl);
429437
aregion->ops->lkey_id_put(aregion, lkey_id);
@@ -438,17 +446,30 @@ __mlxsw_sp_acl_atcam_entry_add(struct mlxsw_sp *mlxsw_sp,
438446
struct mlxsw_sp_acl_tcam_region *region = aregion->region;
439447
char mask[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN] = { 0 };
440448
struct mlxsw_afk *afk = mlxsw_sp_acl_afk(mlxsw_sp->acl);
449+
const struct mlxsw_sp_acl_erp_delta *delta;
441450
struct mlxsw_sp_acl_erp_mask *erp_mask;
442451
int err;
443452

444453
mlxsw_afk_encode(afk, region->key_info, &rulei->values,
445-
aentry->ht_key.enc_key, mask);
454+
aentry->full_enc_key, mask);
446455

447456
erp_mask = mlxsw_sp_acl_erp_mask_get(aregion, mask, false);
448457
if (IS_ERR(erp_mask))
449458
return PTR_ERR(erp_mask);
450459
aentry->erp_mask = erp_mask;
451460
aentry->ht_key.erp_id = mlxsw_sp_acl_erp_mask_erp_id(erp_mask);
461+
memcpy(aentry->ht_key.enc_key, aentry->full_enc_key,
462+
sizeof(aentry->ht_key.enc_key));
463+
464+
/* Compute all needed delta information and clear the delta bits
465+
* from the encrypted key.
466+
*/
467+
delta = mlxsw_sp_acl_erp_delta(aentry->erp_mask);
468+
aentry->delta_info.start = mlxsw_sp_acl_erp_delta_start(delta);
469+
aentry->delta_info.mask = mlxsw_sp_acl_erp_delta_mask(delta);
470+
aentry->delta_info.value =
471+
mlxsw_sp_acl_erp_delta_value(delta, aentry->full_enc_key);
472+
mlxsw_sp_acl_erp_delta_clear(delta, aentry->ht_key.enc_key);
452473

453474
/* We can't insert identical rules into the A-TCAM, so fail and
454475
* let the rule spill into C-TCAM

drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_erp.c

Lines changed: 187 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ struct mlxsw_sp_acl_erp_core {
2929

3030
struct mlxsw_sp_acl_erp_key {
3131
char mask[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN];
32+
#define __MASK_LEN 0x38
33+
#define __MASK_IDX(i) (__MASK_LEN - (i) - 1)
3234
bool ctcam;
3335
};
3436

@@ -58,6 +60,7 @@ struct mlxsw_sp_acl_erp_table {
5860
unsigned int num_atcam_erps;
5961
unsigned int num_max_atcam_erps;
6062
unsigned int num_ctcam_erps;
63+
unsigned int num_deltas;
6164
struct objagg *objagg;
6265
};
6366

@@ -629,7 +632,7 @@ __mlxsw_sp_acl_erp_table_other_inc(struct mlxsw_sp_acl_erp_table *erp_table,
629632
{
630633
int err;
631634

632-
/* If there are C-TCAM eRPs in use we need to transition
635+
/* If there are C-TCAM eRP or deltas in use we need to transition
633636
* the region to use eRP table, if it is not already done
634637
*/
635638
if (erp_table->ops != &erp_two_masks_ops &&
@@ -639,7 +642,7 @@ __mlxsw_sp_acl_erp_table_other_inc(struct mlxsw_sp_acl_erp_table *erp_table,
639642
return err;
640643
}
641644

642-
/* When C-TCAM is used, the eRP table must be used */
645+
/* When C-TCAM or deltas are used, the eRP table must be used */
643646
if (erp_table->ops != &erp_multiple_masks_ops)
644647
erp_table->ops = &erp_multiple_masks_ops;
645648

@@ -654,17 +657,23 @@ static int mlxsw_sp_acl_erp_ctcam_inc(struct mlxsw_sp_acl_erp_table *erp_table)
654657
&erp_table->num_ctcam_erps);
655658
}
656659

660+
static int mlxsw_sp_acl_erp_delta_inc(struct mlxsw_sp_acl_erp_table *erp_table)
661+
{
662+
return __mlxsw_sp_acl_erp_table_other_inc(erp_table,
663+
&erp_table->num_deltas);
664+
}
665+
657666
static void
658667
__mlxsw_sp_acl_erp_table_other_dec(struct mlxsw_sp_acl_erp_table *erp_table,
659668
unsigned int *dec_num)
660669
{
661670
(*dec_num)--;
662671

663-
/* If there are no C-TCAM eRPs in use, the state we
672+
/* If there are no C-TCAM eRP or deltas in use, the state we
664673
* transition to depends on the number of A-TCAM eRPs currently
665674
* in use.
666675
*/
667-
if (erp_table->num_ctcam_erps > 0)
676+
if (erp_table->num_ctcam_erps > 0 || erp_table->num_deltas > 0)
668677
return;
669678

670679
switch (erp_table->num_atcam_erps) {
@@ -706,6 +715,12 @@ static void mlxsw_sp_acl_erp_ctcam_dec(struct mlxsw_sp_acl_erp_table *erp_table)
706715
&erp_table->num_ctcam_erps);
707716
}
708717

718+
static void mlxsw_sp_acl_erp_delta_dec(struct mlxsw_sp_acl_erp_table *erp_table)
719+
{
720+
__mlxsw_sp_acl_erp_table_other_dec(erp_table,
721+
&erp_table->num_deltas);
722+
}
723+
709724
static struct mlxsw_sp_acl_erp *
710725
mlxsw_sp_acl_erp_ctcam_mask_create(struct mlxsw_sp_acl_erp_table *erp_table,
711726
struct mlxsw_sp_acl_erp_key *key)
@@ -813,7 +828,8 @@ mlxsw_sp_acl_erp_mask_destroy(struct mlxsw_sp_acl_erp_table *erp_table,
813828
mlxsw_sp_acl_erp_index_put(erp_table, erp->index);
814829
mlxsw_sp_acl_erp_generic_destroy(erp);
815830

816-
if (erp_table->num_atcam_erps == 2 && erp_table->num_ctcam_erps == 0)
831+
if (erp_table->num_atcam_erps == 2 && erp_table->num_ctcam_erps == 0 &&
832+
erp_table->num_deltas == 0)
817833
erp_table->ops = &erp_two_masks_ops;
818834
}
819835

@@ -961,14 +977,179 @@ u8 mlxsw_sp_acl_erp_mask_erp_id(const struct mlxsw_sp_acl_erp_mask *erp_mask)
961977
return erp->id;
962978
}
963979

980+
struct mlxsw_sp_acl_erp_delta {
981+
struct mlxsw_sp_acl_erp_key key;
982+
u16 start;
983+
u8 mask;
984+
};
985+
986+
u16 mlxsw_sp_acl_erp_delta_start(const struct mlxsw_sp_acl_erp_delta *delta)
987+
{
988+
return delta->start;
989+
}
990+
991+
u8 mlxsw_sp_acl_erp_delta_mask(const struct mlxsw_sp_acl_erp_delta *delta)
992+
{
993+
return delta->mask;
994+
}
995+
996+
u8 mlxsw_sp_acl_erp_delta_value(const struct mlxsw_sp_acl_erp_delta *delta,
997+
const char *enc_key)
998+
{
999+
u16 start = delta->start;
1000+
u8 mask = delta->mask;
1001+
u16 tmp;
1002+
1003+
if (!mask)
1004+
return 0;
1005+
1006+
tmp = (unsigned char) enc_key[__MASK_IDX(start / 8)];
1007+
if (start / 8 + 1 < __MASK_LEN)
1008+
tmp |= (unsigned char) enc_key[__MASK_IDX(start / 8 + 1)] << 8;
1009+
tmp >>= start % 8;
1010+
tmp &= mask;
1011+
return tmp;
1012+
}
1013+
1014+
void mlxsw_sp_acl_erp_delta_clear(const struct mlxsw_sp_acl_erp_delta *delta,
1015+
const char *enc_key)
1016+
{
1017+
u16 start = delta->start;
1018+
u8 mask = delta->mask;
1019+
unsigned char *byte;
1020+
u16 tmp;
1021+
1022+
tmp = mask;
1023+
tmp <<= start % 8;
1024+
tmp = ~tmp;
1025+
1026+
byte = (unsigned char *) &enc_key[__MASK_IDX(start / 8)];
1027+
*byte &= tmp & 0xff;
1028+
if (start / 8 + 1 < __MASK_LEN) {
1029+
byte = (unsigned char *) &enc_key[__MASK_IDX(start / 8 + 1)];
1030+
*byte &= (tmp >> 8) & 0xff;
1031+
}
1032+
}
1033+
1034+
static const struct mlxsw_sp_acl_erp_delta
1035+
mlxsw_sp_acl_erp_delta_default = {};
1036+
1037+
const struct mlxsw_sp_acl_erp_delta *
1038+
mlxsw_sp_acl_erp_delta(const struct mlxsw_sp_acl_erp_mask *erp_mask)
1039+
{
1040+
struct objagg_obj *objagg_obj = (struct objagg_obj *) erp_mask;
1041+
const struct mlxsw_sp_acl_erp_delta *delta;
1042+
1043+
delta = objagg_obj_delta_priv(objagg_obj);
1044+
if (!delta)
1045+
delta = &mlxsw_sp_acl_erp_delta_default;
1046+
return delta;
1047+
}
1048+
1049+
static int
1050+
mlxsw_sp_acl_erp_delta_fill(const struct mlxsw_sp_acl_erp_key *parent_key,
1051+
const struct mlxsw_sp_acl_erp_key *key,
1052+
u16 *delta_start, u8 *delta_mask)
1053+
{
1054+
int offset = 0;
1055+
int si = -1;
1056+
u16 pmask;
1057+
u16 mask;
1058+
int i;
1059+
1060+
/* The difference between 2 masks can be up to 8 consecutive bits. */
1061+
for (i = 0; i < __MASK_LEN; i++) {
1062+
if (parent_key->mask[__MASK_IDX(i)] == key->mask[__MASK_IDX(i)])
1063+
continue;
1064+
if (si == -1)
1065+
si = i;
1066+
else if (si != i - 1)
1067+
return -EINVAL;
1068+
}
1069+
if (si == -1) {
1070+
/* The masks are the same, this cannot happen.
1071+
* That means the caller is broken.
1072+
*/
1073+
WARN_ON(1);
1074+
*delta_start = 0;
1075+
*delta_mask = 0;
1076+
return 0;
1077+
}
1078+
pmask = (unsigned char) parent_key->mask[__MASK_IDX(si)];
1079+
mask = (unsigned char) key->mask[__MASK_IDX(si)];
1080+
if (si + 1 < __MASK_LEN) {
1081+
pmask |= (unsigned char) parent_key->mask[__MASK_IDX(si + 1)] << 8;
1082+
mask |= (unsigned char) key->mask[__MASK_IDX(si + 1)] << 8;
1083+
}
1084+
1085+
if ((pmask ^ mask) & pmask)
1086+
return -EINVAL;
1087+
mask &= ~pmask;
1088+
while (!(mask & (1 << offset)))
1089+
offset++;
1090+
while (!(mask & 1))
1091+
mask >>= 1;
1092+
if (mask & 0xff00)
1093+
return -EINVAL;
1094+
1095+
*delta_start = si * 8 + offset;
1096+
*delta_mask = mask;
1097+
1098+
return 0;
1099+
}
1100+
9641101
static void *mlxsw_sp_acl_erp_delta_create(void *priv, void *parent_obj,
9651102
void *obj)
9661103
{
967-
return ERR_PTR(-EOPNOTSUPP);
1104+
struct mlxsw_sp_acl_erp_key *parent_key = parent_obj;
1105+
struct mlxsw_sp_acl_atcam_region *aregion = priv;
1106+
struct mlxsw_sp_acl_erp_table *erp_table = aregion->erp_table;
1107+
struct mlxsw_sp_acl_erp_key *key = obj;
1108+
struct mlxsw_sp_acl_erp_delta *delta;
1109+
u16 delta_start;
1110+
u8 delta_mask;
1111+
int err;
1112+
1113+
if (parent_key->ctcam || key->ctcam)
1114+
return ERR_PTR(-EINVAL);
1115+
err = mlxsw_sp_acl_erp_delta_fill(parent_key, key,
1116+
&delta_start, &delta_mask);
1117+
if (err)
1118+
return ERR_PTR(-EINVAL);
1119+
1120+
delta = kzalloc(sizeof(*delta), GFP_KERNEL);
1121+
if (!delta)
1122+
return ERR_PTR(-ENOMEM);
1123+
delta->start = delta_start;
1124+
delta->mask = delta_mask;
1125+
1126+
err = mlxsw_sp_acl_erp_delta_inc(erp_table);
1127+
if (err)
1128+
goto err_erp_delta_inc;
1129+
1130+
memcpy(&delta->key, key, sizeof(*key));
1131+
err = mlxsw_sp_acl_erp_master_mask_set(erp_table, &delta->key);
1132+
if (err)
1133+
goto err_master_mask_set;
1134+
1135+
return delta;
1136+
1137+
err_master_mask_set:
1138+
mlxsw_sp_acl_erp_delta_dec(erp_table);
1139+
err_erp_delta_inc:
1140+
kfree(delta);
1141+
return ERR_PTR(err);
9681142
}
9691143

9701144
static void mlxsw_sp_acl_erp_delta_destroy(void *priv, void *delta_priv)
9711145
{
1146+
struct mlxsw_sp_acl_erp_delta *delta = delta_priv;
1147+
struct mlxsw_sp_acl_atcam_region *aregion = priv;
1148+
struct mlxsw_sp_acl_erp_table *erp_table = aregion->erp_table;
1149+
1150+
mlxsw_sp_acl_erp_master_mask_clear(erp_table, &delta->key);
1151+
mlxsw_sp_acl_erp_delta_dec(erp_table);
1152+
kfree(delta);
9721153
}
9731154

9741155
static void *mlxsw_sp_acl_erp_root_create(void *priv, void *obj)

drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,9 @@ struct mlxsw_sp_acl_atcam_region {
154154
};
155155

156156
struct mlxsw_sp_acl_atcam_entry_ht_key {
157-
char enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded key */
157+
char enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded key,
158+
* minus delta bits.
159+
*/
158160
u8 erp_id;
159161
};
160162

@@ -165,6 +167,12 @@ struct mlxsw_sp_acl_atcam_chunk {
165167
struct mlxsw_sp_acl_atcam_entry {
166168
struct rhash_head ht_node;
167169
struct mlxsw_sp_acl_atcam_entry_ht_key ht_key;
170+
char full_enc_key[MLXSW_REG_PTCEX_FLEX_KEY_BLOCKS_LEN]; /* Encoded key */
171+
struct {
172+
u16 start;
173+
u8 mask;
174+
u8 value;
175+
} delta_info;
168176
struct mlxsw_sp_acl_ctcam_entry centry;
169177
struct mlxsw_sp_acl_atcam_lkey_id *lkey_id;
170178
struct mlxsw_sp_acl_erp_mask *erp_mask;
@@ -209,11 +217,22 @@ int mlxsw_sp_acl_atcam_init(struct mlxsw_sp *mlxsw_sp,
209217
void mlxsw_sp_acl_atcam_fini(struct mlxsw_sp *mlxsw_sp,
210218
struct mlxsw_sp_acl_atcam *atcam);
211219

220+
struct mlxsw_sp_acl_erp_delta;
221+
222+
u16 mlxsw_sp_acl_erp_delta_start(const struct mlxsw_sp_acl_erp_delta *delta);
223+
u8 mlxsw_sp_acl_erp_delta_mask(const struct mlxsw_sp_acl_erp_delta *delta);
224+
u8 mlxsw_sp_acl_erp_delta_value(const struct mlxsw_sp_acl_erp_delta *delta,
225+
const char *enc_key);
226+
void mlxsw_sp_acl_erp_delta_clear(const struct mlxsw_sp_acl_erp_delta *delta,
227+
const char *enc_key);
228+
212229
struct mlxsw_sp_acl_erp_mask;
213230

214231
bool
215232
mlxsw_sp_acl_erp_mask_is_ctcam(const struct mlxsw_sp_acl_erp_mask *erp_mask);
216233
u8 mlxsw_sp_acl_erp_mask_erp_id(const struct mlxsw_sp_acl_erp_mask *erp_mask);
234+
const struct mlxsw_sp_acl_erp_delta *
235+
mlxsw_sp_acl_erp_delta(const struct mlxsw_sp_acl_erp_mask *erp_mask);
217236
struct mlxsw_sp_acl_erp_mask *
218237
mlxsw_sp_acl_erp_mask_get(struct mlxsw_sp_acl_atcam_region *aregion,
219238
const char *mask, bool ctcam);

0 commit comments

Comments
 (0)