net/sched: sch_ets: properly init all active DRR list handles

Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2025552
Upstream Status: net-next.git commit 454d3e1ae057

commit 454d3e1ae057a1e09a15905b06b860f60d6c14d0
Author: Davide Caratti <dcaratti@redhat.com>
Date:   Thu Oct 7 15:05:02 2021 +0200

    net/sched: sch_ets: properly init all active DRR list handles

    leaf classes of ETS qdiscs are served in strict priority or deficit round
    robin (DRR), depending on the value of 'nstrict'. Since this value can be
    changed while traffic is running, we need to be sure that the active list
    of DRR classes can be updated at any time, so:

    1) call INIT_LIST_HEAD(&alist) on all leaf classes in .init(), before the
       first packet hits any of them.
    2) ensure that 'alist' is not overwritten with zeros when a leaf class is
       no more strict priority nor DRR (i.e. array elements beyond 'nbands').

    Link: https://lore.kernel.org/netdev/YS%2FoZ+f0Nr8eQkzH@dcaratti.users.ipa.redhat.com
    Suggested-by: Cong Wang <cong.wang@bytedance.com>
    Signed-off-by: Davide Caratti <dcaratti@redhat.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>

Signed-off-by: Davide Caratti <dcaratti@redhat.com>
This commit is contained in:
Davide Caratti 2021-12-09 12:01:43 +01:00
parent f8ba111f40
commit 4b325b1480
1 changed files with 9 additions and 3 deletions

View File

@ -661,7 +661,6 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt,
q->nbands = nbands;
for (i = nstrict; i < q->nstrict; i++) {
INIT_LIST_HEAD(&q->classes[i].alist);
if (q->classes[i].qdisc->q.qlen) {
list_add_tail(&q->classes[i].alist, &q->active);
q->classes[i].deficit = quanta[i];
@ -687,7 +686,11 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt,
ets_offload_change(sch);
for (i = q->nbands; i < oldbands; i++) {
qdisc_put(q->classes[i].qdisc);
memset(&q->classes[i], 0, sizeof(q->classes[i]));
q->classes[i].qdisc = NULL;
q->classes[i].quantum = 0;
q->classes[i].deficit = 0;
memset(&q->classes[i].bstats, 0, sizeof(q->classes[i].bstats));
memset(&q->classes[i].qstats, 0, sizeof(q->classes[i].qstats));
}
return 0;
}
@ -696,7 +699,7 @@ static int ets_qdisc_init(struct Qdisc *sch, struct nlattr *opt,
struct netlink_ext_ack *extack)
{
struct ets_sched *q = qdisc_priv(sch);
int err;
int err, i;
if (!opt)
return -EINVAL;
@ -706,6 +709,9 @@ static int ets_qdisc_init(struct Qdisc *sch, struct nlattr *opt,
return err;
INIT_LIST_HEAD(&q->active);
for (i = 0; i < TCQ_ETS_MAX_BANDS; i++)
INIT_LIST_HEAD(&q->classes[i].alist);
return ets_qdisc_change(sch, opt, extack);
}