Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 926e61b7 authored by Jarek Poplawski's avatar Jarek Poplawski Committed by David S. Miller
Browse files

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: default avatarJarek Poplawski <jarkao2@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ca519274
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -81,7 +81,7 @@ struct Qdisc
struct Qdisc_class_ops
{
	/* Child qdisc manipulation */
	unsigned int		(*select_queue)(struct Qdisc *, struct tcmsg *);
	struct netdev_queue *	(*select_queue)(struct Qdisc *, struct tcmsg *);
	int			(*graft)(struct Qdisc *, unsigned long cl,
					struct Qdisc *, struct Qdisc **);
	struct Qdisc *		(*leaf)(struct Qdisc *, unsigned long cl);
+7 −3
Original line number Diff line number Diff line
@@ -1116,12 +1116,16 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
				 tcm->tcm_parent, tcm->tcm_parent,
				 tca, &err);
	else {
		unsigned int ntx = 0;
		struct netdev_queue *dev_queue;

		if (p && p->ops->cl_ops && p->ops->cl_ops->select_queue)
			ntx = p->ops->cl_ops->select_queue(p, tcm);
			dev_queue = p->ops->cl_ops->select_queue(p, tcm);
		else if (p)
			dev_queue = p->dev_queue;
		else
			dev_queue = netdev_get_tx_queue(dev, 0);

		q = qdisc_create(dev, netdev_get_tx_queue(dev, ntx), p,
		q = qdisc_create(dev, dev_queue, p,
				 tcm->tcm_parent, tcm->tcm_handle,
				 tca, &err);
	}
+9 −4
Original line number Diff line number Diff line
@@ -125,13 +125,18 @@ static struct netdev_queue *mq_queue_get(struct Qdisc *sch, unsigned long cl)
	return netdev_get_tx_queue(dev, ntx);
}

static unsigned int mq_select_queue(struct Qdisc *sch, struct tcmsg *tcm)
static struct netdev_queue *mq_select_queue(struct Qdisc *sch,
					    struct tcmsg *tcm)
{
	unsigned int ntx = TC_H_MIN(tcm->tcm_parent);
	struct netdev_queue *dev_queue = mq_queue_get(sch, ntx);

	if (!mq_queue_get(sch, ntx))
		return 0;
	return ntx - 1;
	if (!dev_queue) {
		struct net_device *dev = qdisc_dev(sch);

		return netdev_get_tx_queue(dev, 0);
	}
	return dev_queue;
}

static int mq_graft(struct Qdisc *sch, unsigned long cl, struct Qdisc *new,