From ff8583b15770a06237970a85c7cc02e3bde98d13 Mon Sep 17 00:00:00 2001 From: Davide Caratti Date: Thu, 7 Oct 2021 15:05:02 +0200 Subject: [PATCH 037/158] 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 Signed-off-by: Davide Caratti Signed-off-by: David S. Miller Signed-off-by: Sebastian Andrzej Siewior --- net/sched/sch_ets.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) Index: linux-5.15.19-rt29/net/sched/sch_ets.c =================================================================== --- linux-5.15.19-rt29.orig/net/sched/sch_ets.c +++ linux-5.15.19-rt29/net/sched/sch_ets.c @@ -661,7 +661,6 @@ static int ets_qdisc_change(struct Qdisc 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]; @@ -689,7 +688,11 @@ static int ets_qdisc_change(struct Qdisc 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; } @@ -698,7 +701,7 @@ static int ets_qdisc_init(struct Qdisc * struct netlink_ext_ack *extack) { struct ets_sched *q = qdisc_priv(sch); - int err; + int err, i; if (!opt) return -EINVAL; @@ -708,6 +711,9 @@ static int ets_qdisc_init(struct Qdisc * 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); }