Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

taprio: don't reject same mqprio settings

The taprio qdisc allows to set mqprio setting but only once. In case
if mqprio settings are provided next time the error is returned as
it's not allowed to change traffic class mapping in-flignt and that
is normal. But if configuration is absolutely the same - no need to
return error. It allows to provide same command couple times,
changing only base time for instance, or changing only scheds maps,
but leaving mqprio setting w/o modification. It more corresponds the
message: "Changing the traffic mapping of a running schedule is not
supported", so reject mqprio if it's really changed.

Also corrected TC_BITMASK + 1 for consistency, as proposed.

Fixes: a3d43c0d56f1 ("taprio: Add support adding an admin schedule")
Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
Tested-by: Vladimir Oltean <olteanv@gmail.com>
Acked-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Ivan Khoronzhuk and committed by
David S. Miller
b5a0faa3 d4ffb02d

+26 -2
+26 -2
net/sched/sch_taprio.c
··· 922 922 } 923 923 924 924 /* Verify priority mapping uses valid tcs */ 925 - for (i = 0; i < TC_BITMASK + 1; i++) { 925 + for (i = 0; i <= TC_BITMASK; i++) { 926 926 if (qopt->prio_tc_map[i] >= qopt->num_tc) { 927 927 NL_SET_ERR_MSG(extack, "Invalid traffic class in priority to traffic class mapping"); 928 928 return -EINVAL; ··· 1347 1347 return err; 1348 1348 } 1349 1349 1350 + static int taprio_mqprio_cmp(const struct net_device *dev, 1351 + const struct tc_mqprio_qopt *mqprio) 1352 + { 1353 + int i; 1354 + 1355 + if (!mqprio || mqprio->num_tc != dev->num_tc) 1356 + return -1; 1357 + 1358 + for (i = 0; i < mqprio->num_tc; i++) 1359 + if (dev->tc_to_txq[i].count != mqprio->count[i] || 1360 + dev->tc_to_txq[i].offset != mqprio->offset[i]) 1361 + return -1; 1362 + 1363 + for (i = 0; i <= TC_BITMASK; i++) 1364 + if (dev->prio_tc_map[i] != mqprio->prio_tc_map[i]) 1365 + return -1; 1366 + 1367 + return 0; 1368 + } 1369 + 1350 1370 static int taprio_change(struct Qdisc *sch, struct nlattr *opt, 1351 1371 struct netlink_ext_ack *extack) 1352 1372 { ··· 1417 1397 oper = rcu_dereference(q->oper_sched); 1418 1398 admin = rcu_dereference(q->admin_sched); 1419 1399 rcu_read_unlock(); 1400 + 1401 + /* no changes - no new mqprio settings */ 1402 + if (!taprio_mqprio_cmp(dev, mqprio)) 1403 + mqprio = NULL; 1420 1404 1421 1405 if (mqprio && (oper || admin)) { 1422 1406 NL_SET_ERR_MSG(extack, "Changing the traffic mapping of a running schedule is not supported"); ··· 1479 1455 mqprio->offset[i]); 1480 1456 1481 1457 /* Always use supplied priority mappings */ 1482 - for (i = 0; i < TC_BITMASK + 1; i++) 1458 + for (i = 0; i <= TC_BITMASK; i++) 1483 1459 netdev_set_prio_tc_map(dev, i, 1484 1460 mqprio->prio_tc_map[i]); 1485 1461 }