Commit 926e61b7c44db83013159ac2f74bccd451607b5a

Authored by Jarek Poplawski
Committed by David S. Miller
1 parent ca519274d5

pkt_sched: Fix tx queue selection in tc_modify_qdisc

After the recent mq change there is the new select_queue qdisc class
method used in tc_modify_qdisc, but it works OK only for direct child
qdiscs of mq qdisc. Grandchildren always get the first tx queue, which
would give wrong qdisc_root etc. results (e.g. for sch_htb as child of
sch_prio). This patch fixes it by using parent's dev_queue for such
grandchildren qdiscs. The select_queue method's return type is changed
BTW.

With feedback from: Patrick McHardy <kaber@trash.net>

Signed-off-by: Jarek Poplawski <jarkao2@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 3 changed files with 17 additions and 8 deletions Side-by-side Diff

include/net/sch_generic.h
... ... @@ -81,7 +81,7 @@
81 81 struct Qdisc_class_ops
82 82 {
83 83 /* Child qdisc manipulation */
84   - unsigned int (*select_queue)(struct Qdisc *, struct tcmsg *);
  84 + struct netdev_queue * (*select_queue)(struct Qdisc *, struct tcmsg *);
85 85 int (*graft)(struct Qdisc *, unsigned long cl,
86 86 struct Qdisc *, struct Qdisc **);
87 87 struct Qdisc * (*leaf)(struct Qdisc *, unsigned long cl);
... ... @@ -1116,12 +1116,16 @@
1116 1116 tcm->tcm_parent, tcm->tcm_parent,
1117 1117 tca, &err);
1118 1118 else {
1119   - unsigned int ntx = 0;
  1119 + struct netdev_queue *dev_queue;
1120 1120  
1121 1121 if (p && p->ops->cl_ops && p->ops->cl_ops->select_queue)
1122   - ntx = p->ops->cl_ops->select_queue(p, tcm);
  1122 + dev_queue = p->ops->cl_ops->select_queue(p, tcm);
  1123 + else if (p)
  1124 + dev_queue = p->dev_queue;
  1125 + else
  1126 + dev_queue = netdev_get_tx_queue(dev, 0);
1123 1127  
1124   - q = qdisc_create(dev, netdev_get_tx_queue(dev, ntx), p,
  1128 + q = qdisc_create(dev, dev_queue, p,
1125 1129 tcm->tcm_parent, tcm->tcm_handle,
1126 1130 tca, &err);
1127 1131 }
... ... @@ -125,13 +125,18 @@
125 125 return netdev_get_tx_queue(dev, ntx);
126 126 }
127 127  
128   -static unsigned int mq_select_queue(struct Qdisc *sch, struct tcmsg *tcm)
  128 +static struct netdev_queue *mq_select_queue(struct Qdisc *sch,
  129 + struct tcmsg *tcm)
129 130 {
130 131 unsigned int ntx = TC_H_MIN(tcm->tcm_parent);
  132 + struct netdev_queue *dev_queue = mq_queue_get(sch, ntx);
131 133  
132   - if (!mq_queue_get(sch, ntx))
133   - return 0;
134   - return ntx - 1;
  134 + if (!dev_queue) {
  135 + struct net_device *dev = qdisc_dev(sch);
  136 +
  137 + return netdev_get_tx_queue(dev, 0);
  138 + }
  139 + return dev_queue;
135 140 }
136 141  
137 142 static int mq_graft(struct Qdisc *sch, unsigned long cl, struct Qdisc *new,