Skip to content

Commit 3230290

Browse files
Alexander Duyckdavem330
authored andcommitted
mqprio: Reserve last 32 classid values for HW traffic classes and misc IDs
This patch makes a slight tweak to mqprio in order to bring the classid values used back in line with what is used for mq. The general idea is to reserve values :ffe0 - :ffef to identify hardware traffic classes normally reported via dev->num_tc. By doing this we can maintain a consistent behavior with mq for classid where :1 - :ffdf will represent a physical qdisc mapped onto a Tx queue represented by classid - 1, and the traffic classes will be mapped onto a known subset of classid values reserved for our virtual qdiscs. Note I reserved the range from :fff0 - :ffff since this way we might be able to reuse these classid values with clsact and ingress which would mean that for mq, mqprio, ingress, and clsact we should be able to maintain a similar classid layout. Signed-off-by: Alexander Duyck <[email protected]> Tested-by: Jesus Sanchez-Palencia <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent af28f6f commit 3230290

File tree

2 files changed

+47
-33
lines changed

2 files changed

+47
-33
lines changed

include/uapi/linux/pkt_sched.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ struct tc_estimator {
7474
#define TC_H_INGRESS (0xFFFFFFF1U)
7575
#define TC_H_CLSACT TC_H_INGRESS
7676

77+
#define TC_H_MIN_PRIORITY 0xFFE0U
7778
#define TC_H_MIN_INGRESS 0xFFF2U
7879
#define TC_H_MIN_EGRESS 0xFFF3U
7980

net/sched/sch_mqprio.c

Lines changed: 46 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,10 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt)
153153
if (!netif_is_multiqueue(dev))
154154
return -EOPNOTSUPP;
155155

156+
/* make certain can allocate enough classids to handle queues */
157+
if (dev->num_tx_queues >= TC_H_MIN_PRIORITY)
158+
return -ENOMEM;
159+
156160
if (!opt || nla_len(opt) < sizeof(*qopt))
157161
return -EINVAL;
158162

@@ -305,7 +309,7 @@ static struct netdev_queue *mqprio_queue_get(struct Qdisc *sch,
305309
unsigned long cl)
306310
{
307311
struct net_device *dev = qdisc_dev(sch);
308-
unsigned long ntx = cl - 1 - netdev_get_num_tc(dev);
312+
unsigned long ntx = cl - 1;
309313

310314
if (ntx >= dev->num_tx_queues)
311315
return NULL;
@@ -447,38 +451,35 @@ static unsigned long mqprio_find(struct Qdisc *sch, u32 classid)
447451
struct net_device *dev = qdisc_dev(sch);
448452
unsigned int ntx = TC_H_MIN(classid);
449453

450-
if (ntx > dev->num_tx_queues + netdev_get_num_tc(dev))
451-
return 0;
452-
return ntx;
454+
/* There are essentially two regions here that have valid classid
455+
* values. The first region will have a classid value of 1 through
456+
* num_tx_queues. All of these are backed by actual Qdiscs.
457+
*/
458+
if (ntx < TC_H_MIN_PRIORITY)
459+
return (ntx <= dev->num_tx_queues) ? ntx : 0;
460+
461+
/* The second region represents the hardware traffic classes. These
462+
* are represented by classid values of TC_H_MIN_PRIORITY through
463+
* TC_H_MIN_PRIORITY + netdev_get_num_tc - 1
464+
*/
465+
return ((ntx - TC_H_MIN_PRIORITY) < netdev_get_num_tc(dev)) ? ntx : 0;
453466
}
454467

455468
static int mqprio_dump_class(struct Qdisc *sch, unsigned long cl,
456469
struct sk_buff *skb, struct tcmsg *tcm)
457470
{
458-
struct net_device *dev = qdisc_dev(sch);
471+
if (cl < TC_H_MIN_PRIORITY) {
472+
struct netdev_queue *dev_queue = mqprio_queue_get(sch, cl);
473+
struct net_device *dev = qdisc_dev(sch);
474+
int tc = netdev_txq_to_tc(dev, cl - 1);
459475

460-
if (cl <= netdev_get_num_tc(dev)) {
476+
tcm->tcm_parent = (tc < 0) ? 0 :
477+
TC_H_MAKE(TC_H_MAJ(sch->handle),
478+
TC_H_MIN(tc + TC_H_MIN_PRIORITY));
479+
tcm->tcm_info = dev_queue->qdisc_sleeping->handle;
480+
} else {
461481
tcm->tcm_parent = TC_H_ROOT;
462482
tcm->tcm_info = 0;
463-
} else {
464-
int i;
465-
struct netdev_queue *dev_queue;
466-
467-
dev_queue = mqprio_queue_get(sch, cl);
468-
tcm->tcm_parent = 0;
469-
for (i = 0; i < netdev_get_num_tc(dev); i++) {
470-
struct netdev_tc_txq tc = dev->tc_to_txq[i];
471-
int q_idx = cl - netdev_get_num_tc(dev);
472-
473-
if (q_idx > tc.offset &&
474-
q_idx <= tc.offset + tc.count) {
475-
tcm->tcm_parent =
476-
TC_H_MAKE(TC_H_MAJ(sch->handle),
477-
TC_H_MIN(i + 1));
478-
break;
479-
}
480-
}
481-
tcm->tcm_info = dev_queue->qdisc_sleeping->handle;
482483
}
483484
tcm->tcm_handle |= TC_H_MIN(cl);
484485
return 0;
@@ -489,15 +490,14 @@ static int mqprio_dump_class_stats(struct Qdisc *sch, unsigned long cl,
489490
__releases(d->lock)
490491
__acquires(d->lock)
491492
{
492-
struct net_device *dev = qdisc_dev(sch);
493-
494-
if (cl <= netdev_get_num_tc(dev)) {
493+
if (cl >= TC_H_MIN_PRIORITY) {
495494
int i;
496495
__u32 qlen = 0;
497496
struct Qdisc *qdisc;
498497
struct gnet_stats_queue qstats = {0};
499498
struct gnet_stats_basic_packed bstats = {0};
500-
struct netdev_tc_txq tc = dev->tc_to_txq[cl - 1];
499+
struct net_device *dev = qdisc_dev(sch);
500+
struct netdev_tc_txq tc = dev->tc_to_txq[cl & TC_BITMASK];
501501

502502
/* Drop lock here it will be reclaimed before touching
503503
* statistics this is required because the d->lock we
@@ -550,12 +550,25 @@ static void mqprio_walk(struct Qdisc *sch, struct qdisc_walker *arg)
550550

551551
/* Walk hierarchy with a virtual class per tc */
552552
arg->count = arg->skip;
553-
for (ntx = arg->skip;
554-
ntx < dev->num_tx_queues + netdev_get_num_tc(dev);
555-
ntx++) {
553+
for (ntx = arg->skip; ntx < netdev_get_num_tc(dev); ntx++) {
554+
if (arg->fn(sch, ntx + TC_H_MIN_PRIORITY, arg) < 0) {
555+
arg->stop = 1;
556+
return;
557+
}
558+
arg->count++;
559+
}
560+
561+
/* Pad the values and skip over unused traffic classes */
562+
if (ntx < TC_MAX_QUEUE) {
563+
arg->count = TC_MAX_QUEUE;
564+
ntx = TC_MAX_QUEUE;
565+
}
566+
567+
/* Reset offset, sort out remaining per-queue qdiscs */
568+
for (ntx -= TC_MAX_QUEUE; ntx < dev->num_tx_queues; ntx++) {
556569
if (arg->fn(sch, ntx + 1, arg) < 0) {
557570
arg->stop = 1;
558-
break;
571+
return;
559572
}
560573
arg->count++;
561574
}

0 commit comments

Comments
 (0)