Commit 451b2596 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'htb-fixes'



Maxim Mikityanskiy says:

====================
Bugfixes for HTB

The HTB offload feature introduced a few bugs in HTB. One affects the
non-offload mode, preventing attaching qdiscs to HTB classes, and the
other affects the error flow, when the netdev doesn't support the
offload, but it was requested. This short series fixes them.
====================

Acked-by: default avatarCong Wang <cong.wang@bytedance.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 7a1468ba fb3a3e37
Loading
Loading
Loading
Loading
+13 −6
Original line number Diff line number Diff line
@@ -1020,6 +1020,7 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt,
	struct nlattr *tb[TCA_HTB_MAX + 1];
	struct tc_htb_glob *gopt;
	unsigned int ntx;
	bool offload;
	int err;

	qdisc_watchdog_init(&q->watchdog, sch);
@@ -1044,9 +1045,9 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt,
	if (gopt->version != HTB_VER >> 16)
		return -EINVAL;

	q->offload = nla_get_flag(tb[TCA_HTB_OFFLOAD]);
	offload = nla_get_flag(tb[TCA_HTB_OFFLOAD]);

	if (q->offload) {
	if (offload) {
		if (sch->parent != TC_H_ROOT)
			return -EOPNOTSUPP;

@@ -1076,7 +1077,7 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt,
		q->rate2quantum = 1;
	q->defcls = gopt->defcls;

	if (!q->offload)
	if (!offload)
		return 0;

	for (ntx = 0; ntx < q->num_direct_qdiscs; ntx++) {
@@ -1107,12 +1108,14 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt,
	if (err)
		goto err_free_qdiscs;

	/* Defer this assignment, so that htb_destroy skips offload-related
	 * parts (especially calling ndo_setup_tc) on errors.
	 */
	q->offload = true;

	return 0;

err_free_qdiscs:
	/* TC_HTB_CREATE call failed, avoid any further calls to the driver. */
	q->offload = false;

	for (ntx = 0; ntx < q->num_direct_qdiscs && q->direct_qdiscs[ntx];
	     ntx++)
		qdisc_put(q->direct_qdiscs[ntx]);
@@ -1340,8 +1343,12 @@ htb_select_queue(struct Qdisc *sch, struct tcmsg *tcm)
{
	struct net_device *dev = qdisc_dev(sch);
	struct tc_htb_qopt_offload offload_opt;
	struct htb_sched *q = qdisc_priv(sch);
	int err;

	if (!q->offload)
		return sch->dev_queue;

	offload_opt = (struct tc_htb_qopt_offload) {
		.command = TC_HTB_LEAF_QUERY_QUEUE,
		.classid = TC_H_MIN(tcm->tcm_parent),