Skip to content

Commit 92b7e62

Browse files
committed
Merge branch 'mlxsw-Offload-TC-action-pedit-munge-dsfield'
Ido Schimmel says: ==================== mlxsw: Offload TC action pedit munge dsfield Petr says: The Spectrum switches allow packet prioritization based on DSCP on ingress, and update of DSCP on egress. This is configured through the DCB APP rules. For some use cases, assigning a custom DSCP value based on an ACL match is a better tool. To that end, offload FLOW_ACTION_MANGLE to permit changing of dsfield as a whole, or DSCP and ECN values in isolation. After fixing a commentary nit in patch #1, and mlxsw naming in patch #2, patches #3 and #4 add the offload to mlxsw. Patch #5 adds a forwarding selftest for pedit dsfield, applicable to SW as well as HW datapaths. Patch #6 adds a mlxsw-specific test to verify DSCP rewrite due to DCB APP rules is not performed on pedited packets. The tests only cover IPv4 dsfield setting. We have tests for IPv6 as well, but would like to postpone their contribution until the corresponding iproute patches have been accepted. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 1434021 + 9a9dffc commit 92b7e62

File tree

8 files changed

+515
-8
lines changed

8 files changed

+515
-8
lines changed

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

Lines changed: 127 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,15 +1248,51 @@ EXPORT_SYMBOL(mlxsw_afa_block_append_mirror);
12481248
#define MLXSW_AFA_QOS_CODE 0x06
12491249
#define MLXSW_AFA_QOS_SIZE 1
12501250

1251-
enum mlxsw_afa_qos_cmd {
1251+
enum mlxsw_afa_qos_ecn_cmd {
12521252
/* Do nothing */
1253-
MLXSW_AFA_QOS_CMD_NOP,
1254-
/* Set a field */
1255-
MLXSW_AFA_QOS_CMD_SET,
1253+
MLXSW_AFA_QOS_ECN_CMD_NOP,
1254+
/* Set ECN to afa_qos_ecn */
1255+
MLXSW_AFA_QOS_ECN_CMD_SET,
1256+
};
1257+
1258+
/* afa_qos_ecn_cmd
1259+
*/
1260+
MLXSW_ITEM32(afa, qos, ecn_cmd, 0x04, 29, 3);
1261+
1262+
/* afa_qos_ecn
1263+
* ECN value.
1264+
*/
1265+
MLXSW_ITEM32(afa, qos, ecn, 0x04, 24, 2);
1266+
1267+
enum mlxsw_afa_qos_dscp_cmd {
1268+
/* Do nothing */
1269+
MLXSW_AFA_QOS_DSCP_CMD_NOP,
1270+
/* Set DSCP 3 LSB bits according to dscp[2:0] */
1271+
MLXSW_AFA_QOS_DSCP_CMD_SET_3LSB,
1272+
/* Set DSCP 3 MSB bits according to dscp[5:3] */
1273+
MLXSW_AFA_QOS_DSCP_CMD_SET_3MSB,
1274+
/* Set DSCP 6 bits according to dscp[5:0] */
1275+
MLXSW_AFA_QOS_DSCP_CMD_SET_ALL,
1276+
};
1277+
1278+
/* afa_qos_dscp_cmd
1279+
* DSCP command.
1280+
*/
1281+
MLXSW_ITEM32(afa, qos, dscp_cmd, 0x04, 14, 2);
1282+
1283+
/* afa_qos_dscp
1284+
* DSCP value.
1285+
*/
1286+
MLXSW_ITEM32(afa, qos, dscp, 0x04, 0, 6);
1287+
1288+
enum mlxsw_afa_qos_switch_prio_cmd {
1289+
/* Do nothing */
1290+
MLXSW_AFA_QOS_SWITCH_PRIO_CMD_NOP,
1291+
/* Set Switch Priority to afa_qos_switch_prio */
1292+
MLXSW_AFA_QOS_SWITCH_PRIO_CMD_SET,
12561293
};
12571294

12581295
/* afa_qos_switch_prio_cmd
1259-
* Switch Priority command as per mlxsw_afa_qos_cmd.
12601296
*/
12611297
MLXSW_ITEM32(afa, qos, switch_prio_cmd, 0x08, 14, 2);
12621298

@@ -1265,14 +1301,98 @@ MLXSW_ITEM32(afa, qos, switch_prio_cmd, 0x08, 14, 2);
12651301
*/
12661302
MLXSW_ITEM32(afa, qos, switch_prio, 0x08, 0, 4);
12671303

1304+
enum mlxsw_afa_qos_dscp_rw {
1305+
MLXSW_AFA_QOS_DSCP_RW_PRESERVE,
1306+
MLXSW_AFA_QOS_DSCP_RW_SET,
1307+
MLXSW_AFA_QOS_DSCP_RW_CLEAR,
1308+
};
1309+
1310+
/* afa_qos_dscp_rw
1311+
* DSCP Re-write Enable. Controlling the rewrite_enable for DSCP.
1312+
*/
1313+
MLXSW_ITEM32(afa, qos, dscp_rw, 0x0C, 30, 2);
1314+
1315+
static inline void
1316+
mlxsw_afa_qos_ecn_pack(char *payload,
1317+
enum mlxsw_afa_qos_ecn_cmd ecn_cmd, u8 ecn)
1318+
{
1319+
mlxsw_afa_qos_ecn_cmd_set(payload, ecn_cmd);
1320+
mlxsw_afa_qos_ecn_set(payload, ecn);
1321+
}
1322+
1323+
static inline void
1324+
mlxsw_afa_qos_dscp_pack(char *payload,
1325+
enum mlxsw_afa_qos_dscp_cmd dscp_cmd, u8 dscp)
1326+
{
1327+
mlxsw_afa_qos_dscp_cmd_set(payload, dscp_cmd);
1328+
mlxsw_afa_qos_dscp_set(payload, dscp);
1329+
}
1330+
12681331
static inline void
12691332
mlxsw_afa_qos_switch_prio_pack(char *payload,
1270-
enum mlxsw_afa_qos_cmd prio_cmd, u8 prio)
1333+
enum mlxsw_afa_qos_switch_prio_cmd prio_cmd,
1334+
u8 prio)
12711335
{
12721336
mlxsw_afa_qos_switch_prio_cmd_set(payload, prio_cmd);
12731337
mlxsw_afa_qos_switch_prio_set(payload, prio);
12741338
}
12751339

1340+
static int __mlxsw_afa_block_append_qos_dsfield(struct mlxsw_afa_block *block,
1341+
bool set_dscp, u8 dscp,
1342+
bool set_ecn, u8 ecn,
1343+
struct netlink_ext_ack *extack)
1344+
{
1345+
char *act = mlxsw_afa_block_append_action(block,
1346+
MLXSW_AFA_QOS_CODE,
1347+
MLXSW_AFA_QOS_SIZE);
1348+
1349+
if (IS_ERR(act)) {
1350+
NL_SET_ERR_MSG_MOD(extack, "Cannot append QOS action");
1351+
return PTR_ERR(act);
1352+
}
1353+
1354+
if (set_ecn)
1355+
mlxsw_afa_qos_ecn_pack(act, MLXSW_AFA_QOS_ECN_CMD_SET, ecn);
1356+
if (set_dscp) {
1357+
mlxsw_afa_qos_dscp_pack(act, MLXSW_AFA_QOS_DSCP_CMD_SET_ALL,
1358+
dscp);
1359+
mlxsw_afa_qos_dscp_rw_set(act, MLXSW_AFA_QOS_DSCP_RW_CLEAR);
1360+
}
1361+
1362+
return 0;
1363+
}
1364+
1365+
int mlxsw_afa_block_append_qos_dsfield(struct mlxsw_afa_block *block,
1366+
u8 dsfield,
1367+
struct netlink_ext_ack *extack)
1368+
{
1369+
return __mlxsw_afa_block_append_qos_dsfield(block,
1370+
true, dsfield >> 2,
1371+
true, dsfield & 0x03,
1372+
extack);
1373+
}
1374+
EXPORT_SYMBOL(mlxsw_afa_block_append_qos_dsfield);
1375+
1376+
int mlxsw_afa_block_append_qos_dscp(struct mlxsw_afa_block *block,
1377+
u8 dscp, struct netlink_ext_ack *extack)
1378+
{
1379+
return __mlxsw_afa_block_append_qos_dsfield(block,
1380+
true, dscp,
1381+
false, 0,
1382+
extack);
1383+
}
1384+
EXPORT_SYMBOL(mlxsw_afa_block_append_qos_dscp);
1385+
1386+
int mlxsw_afa_block_append_qos_ecn(struct mlxsw_afa_block *block,
1387+
u8 ecn, struct netlink_ext_ack *extack)
1388+
{
1389+
return __mlxsw_afa_block_append_qos_dsfield(block,
1390+
false, 0,
1391+
true, ecn,
1392+
extack);
1393+
}
1394+
EXPORT_SYMBOL(mlxsw_afa_block_append_qos_ecn);
1395+
12761396
int mlxsw_afa_block_append_qos_switch_prio(struct mlxsw_afa_block *block,
12771397
u8 prio,
12781398
struct netlink_ext_ack *extack)
@@ -1285,7 +1405,7 @@ int mlxsw_afa_block_append_qos_switch_prio(struct mlxsw_afa_block *block,
12851405
NL_SET_ERR_MSG_MOD(extack, "Cannot append QOS action");
12861406
return PTR_ERR(act);
12871407
}
1288-
mlxsw_afa_qos_switch_prio_pack(act, MLXSW_AFA_QOS_CMD_SET,
1408+
mlxsw_afa_qos_switch_prio_pack(act, MLXSW_AFA_QOS_SWITCH_PRIO_CMD_SET,
12891409
prio);
12901410
return 0;
12911411
}

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@ int mlxsw_afa_block_append_vlan_modify(struct mlxsw_afa_block *block,
6565
int mlxsw_afa_block_append_qos_switch_prio(struct mlxsw_afa_block *block,
6666
u8 prio,
6767
struct netlink_ext_ack *extack);
68+
int mlxsw_afa_block_append_qos_dsfield(struct mlxsw_afa_block *block,
69+
u8 dsfield,
70+
struct netlink_ext_ack *extack);
71+
int mlxsw_afa_block_append_qos_dscp(struct mlxsw_afa_block *block,
72+
u8 dscp, struct netlink_ext_ack *extack);
73+
int mlxsw_afa_block_append_qos_ecn(struct mlxsw_afa_block *block,
74+
u8 ecn, struct netlink_ext_ack *extack);
6875
int mlxsw_afa_block_append_allocated_counter(struct mlxsw_afa_block *block,
6976
u32 counter_index);
7077
int mlxsw_afa_block_append_counter(struct mlxsw_afa_block *block,

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,11 @@ int mlxsw_sp_acl_rulei_act_vlan(struct mlxsw_sp *mlxsw_sp,
749749
int mlxsw_sp_acl_rulei_act_priority(struct mlxsw_sp *mlxsw_sp,
750750
struct mlxsw_sp_acl_rule_info *rulei,
751751
u32 prio, struct netlink_ext_ack *extack);
752+
int mlxsw_sp_acl_rulei_act_mangle(struct mlxsw_sp *mlxsw_sp,
753+
struct mlxsw_sp_acl_rule_info *rulei,
754+
enum flow_action_mangle_base htype,
755+
u32 offset, u32 mask, u32 val,
756+
struct netlink_ext_ack *extack);
752757
int mlxsw_sp_acl_rulei_act_count(struct mlxsw_sp *mlxsw_sp,
753758
struct mlxsw_sp_acl_rule_info *rulei,
754759
struct netlink_ext_ack *extack);

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

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,97 @@ int mlxsw_sp_acl_rulei_act_priority(struct mlxsw_sp *mlxsw_sp,
655655
extack);
656656
}
657657

658+
enum mlxsw_sp_acl_mangle_field {
659+
MLXSW_SP_ACL_MANGLE_FIELD_IP_DSFIELD,
660+
MLXSW_SP_ACL_MANGLE_FIELD_IP_DSCP,
661+
MLXSW_SP_ACL_MANGLE_FIELD_IP_ECN,
662+
};
663+
664+
struct mlxsw_sp_acl_mangle_action {
665+
enum flow_action_mangle_base htype;
666+
/* Offset is u32-aligned. */
667+
u32 offset;
668+
/* Mask bits are unset for the modified field. */
669+
u32 mask;
670+
/* Shift required to extract the set value. */
671+
u32 shift;
672+
enum mlxsw_sp_acl_mangle_field field;
673+
};
674+
675+
#define MLXSW_SP_ACL_MANGLE_ACTION(_htype, _offset, _mask, _shift, _field) \
676+
{ \
677+
.htype = _htype, \
678+
.offset = _offset, \
679+
.mask = _mask, \
680+
.shift = _shift, \
681+
.field = MLXSW_SP_ACL_MANGLE_FIELD_##_field, \
682+
}
683+
684+
#define MLXSW_SP_ACL_MANGLE_ACTION_IP4(_offset, _mask, _shift, _field) \
685+
MLXSW_SP_ACL_MANGLE_ACTION(FLOW_ACT_MANGLE_HDR_TYPE_IP4, \
686+
_offset, _mask, _shift, _field)
687+
688+
#define MLXSW_SP_ACL_MANGLE_ACTION_IP6(_offset, _mask, _shift, _field) \
689+
MLXSW_SP_ACL_MANGLE_ACTION(FLOW_ACT_MANGLE_HDR_TYPE_IP6, \
690+
_offset, _mask, _shift, _field)
691+
692+
static struct mlxsw_sp_acl_mangle_action mlxsw_sp_acl_mangle_actions[] = {
693+
MLXSW_SP_ACL_MANGLE_ACTION_IP4(0, 0xff00ffff, 16, IP_DSFIELD),
694+
MLXSW_SP_ACL_MANGLE_ACTION_IP4(0, 0xff03ffff, 18, IP_DSCP),
695+
MLXSW_SP_ACL_MANGLE_ACTION_IP4(0, 0xfffcffff, 16, IP_ECN),
696+
MLXSW_SP_ACL_MANGLE_ACTION_IP6(0, 0xf00fffff, 20, IP_DSFIELD),
697+
MLXSW_SP_ACL_MANGLE_ACTION_IP6(0, 0xf03fffff, 22, IP_DSCP),
698+
MLXSW_SP_ACL_MANGLE_ACTION_IP6(0, 0xffcfffff, 20, IP_ECN),
699+
};
700+
701+
static int
702+
mlxsw_sp_acl_rulei_act_mangle_field(struct mlxsw_sp *mlxsw_sp,
703+
struct mlxsw_sp_acl_rule_info *rulei,
704+
struct mlxsw_sp_acl_mangle_action *mact,
705+
u32 val, struct netlink_ext_ack *extack)
706+
{
707+
switch (mact->field) {
708+
case MLXSW_SP_ACL_MANGLE_FIELD_IP_DSFIELD:
709+
return mlxsw_afa_block_append_qos_dsfield(rulei->act_block,
710+
val, extack);
711+
case MLXSW_SP_ACL_MANGLE_FIELD_IP_DSCP:
712+
return mlxsw_afa_block_append_qos_dscp(rulei->act_block,
713+
val, extack);
714+
case MLXSW_SP_ACL_MANGLE_FIELD_IP_ECN:
715+
return mlxsw_afa_block_append_qos_ecn(rulei->act_block,
716+
val, extack);
717+
}
718+
719+
/* We shouldn't have gotten a match in the first place! */
720+
WARN_ONCE(1, "Unhandled mangle field");
721+
return -EINVAL;
722+
}
723+
724+
int mlxsw_sp_acl_rulei_act_mangle(struct mlxsw_sp *mlxsw_sp,
725+
struct mlxsw_sp_acl_rule_info *rulei,
726+
enum flow_action_mangle_base htype,
727+
u32 offset, u32 mask, u32 val,
728+
struct netlink_ext_ack *extack)
729+
{
730+
struct mlxsw_sp_acl_mangle_action *mact;
731+
size_t i;
732+
733+
for (i = 0; i < ARRAY_SIZE(mlxsw_sp_acl_mangle_actions); ++i) {
734+
mact = &mlxsw_sp_acl_mangle_actions[i];
735+
if (mact->htype == htype &&
736+
mact->offset == offset &&
737+
mact->mask == mask) {
738+
val >>= mact->shift;
739+
return mlxsw_sp_acl_rulei_act_mangle_field(mlxsw_sp,
740+
rulei, mact,
741+
val, extack);
742+
}
743+
}
744+
745+
NL_SET_ERR_MSG_MOD(extack, "Unsupported mangle field");
746+
return -EINVAL;
747+
}
748+
658749
int mlxsw_sp_acl_rulei_act_count(struct mlxsw_sp *mlxsw_sp,
659750
struct mlxsw_sp_acl_rule_info *rulei,
660751
struct netlink_ext_ack *extack)

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,21 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
158158
return mlxsw_sp_acl_rulei_act_priority(mlxsw_sp, rulei,
159159
act->priority,
160160
extack);
161+
case FLOW_ACTION_MANGLE: {
162+
enum flow_action_mangle_base htype = act->mangle.htype;
163+
__be32 be_mask = (__force __be32) act->mangle.mask;
164+
__be32 be_val = (__force __be32) act->mangle.val;
165+
u32 offset = act->mangle.offset;
166+
u32 mask = be32_to_cpu(be_mask);
167+
u32 val = be32_to_cpu(be_val);
168+
169+
err = mlxsw_sp_acl_rulei_act_mangle(mlxsw_sp, rulei,
170+
htype, offset,
171+
mask, val, extack);
172+
if (err)
173+
return err;
174+
break;
175+
}
161176
default:
162177
NL_SET_ERR_MSG_MOD(extack, "Unsupported action");
163178
dev_err(mlxsw_sp->bus_info->dev, "Unsupported action\n");

include/net/flow_offload.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,8 @@ struct flow_action_entry {
202202
__be16 proto;
203203
u8 prio;
204204
} vlan;
205-
struct { /* FLOW_ACTION_PACKET_EDIT */
205+
struct { /* FLOW_ACTION_MANGLE */
206+
/* FLOW_ACTION_ADD */
206207
enum flow_action_mangle_base htype;
207208
u32 offset;
208209
u32 mask;

tools/testing/selftests/drivers/net/mlxsw/qos_dscp_router.sh

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ ALL_TESTS="
3131
ping_ipv4
3232
test_update
3333
test_no_update
34+
test_pedit_norewrite
3435
test_dscp_leftover
3536
"
3637

@@ -56,6 +57,11 @@ zero()
5657
echo 0
5758
}
5859

60+
three()
61+
{
62+
echo 3
63+
}
64+
5965
h1_create()
6066
{
6167
simple_if_init $h1 192.0.2.1/28
@@ -103,6 +109,9 @@ switch_create()
103109
simple_if_init $swp1 192.0.2.2/28
104110
__simple_if_init $swp2 v$swp1 192.0.2.17/28
105111

112+
tc qdisc add dev $swp1 clsact
113+
tc qdisc add dev $swp2 clsact
114+
106115
lldptool -T -i $swp1 -V APP $(dscp_map 0) >/dev/null
107116
lldptool -T -i $swp2 -V APP $(dscp_map 0) >/dev/null
108117
lldpad_app_wait_set $swp1
@@ -115,6 +124,9 @@ switch_destroy()
115124
lldptool -T -i $swp1 -V APP -d $(dscp_map 0) >/dev/null
116125
lldpad_app_wait_del
117126

127+
tc qdisc del dev $swp2 clsact
128+
tc qdisc del dev $swp1 clsact
129+
118130
__simple_if_fini $swp2 192.0.2.17/28
119131
simple_if_fini $swp1 192.0.2.2/28
120132
}
@@ -223,18 +235,36 @@ __test_update()
223235

224236
test_update()
225237
{
238+
echo "Test net.ipv4.ip_forward_update_priority=1"
226239
__test_update 1 reprioritize
227240
}
228241

229242
test_no_update()
230243
{
244+
echo "Test net.ipv4.ip_forward_update_priority=0"
231245
__test_update 0 echo
232246
}
233247

248+
# Test that when DSCP is updated in pedit, the DSCP rewrite is turned off.
249+
test_pedit_norewrite()
250+
{
251+
echo "Test no DSCP rewrite after DSCP is updated by pedit"
252+
253+
tc filter add dev $swp1 ingress handle 101 pref 1 prot ip flower \
254+
action pedit ex munge ip dsfield set $((3 << 2)) retain 0xfc \
255+
action skbedit priority 3
256+
257+
__test_update 0 three
258+
259+
tc filter del dev $swp1 ingress pref 1
260+
}
261+
234262
# Test that when the last APP rule is removed, the prio->DSCP map is properly
235263
# set to zeroes, and that the last APP rule does not stay active in the ASIC.
236264
test_dscp_leftover()
237265
{
266+
echo "Test that last removed DSCP rule is deconfigured correctly"
267+
238268
lldptool -T -i $swp2 -V APP -d $(dscp_map 0) >/dev/null
239269
lldpad_app_wait_del
240270

0 commit comments

Comments
 (0)