Skip to content

Commit f3e1778

Browse files
committed
sched: Fix detection of empty queues in child qdiscs
jira LE-1907 Rebuild_History Non-Buildable kernel-4.18.0-147.el8 commit-author Toke Høiland-Jørgensen <[email protected]> commit 37d9cf1 Several qdiscs check on enqueue whether the packet was enqueued to a class with an empty queue, in which case the class is activated. This is done by checking if the qlen is exactly 1 after enqueue. However, if GSO splitting is enabled in the child qdisc, a single packet can result in a qlen longer than 1. This means the activation check fails, leading to a stalled queue. Fix this by checking if the queue is empty *before* enqueue, and running the activation logic if this was the case. Reported-by: Pete Heist <[email protected]> Signed-off-by: Toke Høiland-Jørgensen <[email protected]> Signed-off-by: David S. Miller <[email protected]> (cherry picked from commit 37d9cf1) Signed-off-by: Jonathan Maple <[email protected]>
1 parent aded77c commit f3e1778

File tree

3 files changed

+9
-3
lines changed

3 files changed

+9
-3
lines changed

net/sched/sch_drr.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch,
354354
struct drr_sched *q = qdisc_priv(sch);
355355
struct drr_class *cl;
356356
int err = 0;
357+
bool first;
357358

358359
cl = drr_classify(skb, sch, &err);
359360
if (cl == NULL) {
@@ -363,6 +364,7 @@ static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch,
363364
return err;
364365
}
365366

367+
first = !cl->qdisc->q.qlen;
366368
err = qdisc_enqueue(skb, cl->qdisc, to_free);
367369
if (unlikely(err != NET_XMIT_SUCCESS)) {
368370
if (net_xmit_drop_count(err)) {
@@ -372,7 +374,7 @@ static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch,
372374
return err;
373375
}
374376

375-
if (cl->qdisc->q.qlen == 1) {
377+
if (first) {
376378
list_add_tail(&cl->alist, &q->active);
377379
cl->deficit = cl->quantum;
378380
}

net/sched/sch_hfsc.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1542,6 +1542,7 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
15421542
unsigned int len = qdisc_pkt_len(skb);
15431543
struct hfsc_class *cl;
15441544
int uninitialized_var(err);
1545+
bool first;
15451546

15461547
cl = hfsc_classify(skb, sch, &err);
15471548
if (cl == NULL) {
@@ -1551,6 +1552,7 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
15511552
return err;
15521553
}
15531554

1555+
first = !cl->qdisc->q.qlen;
15541556
err = qdisc_enqueue(skb, cl->qdisc, to_free);
15551557
if (unlikely(err != NET_XMIT_SUCCESS)) {
15561558
if (net_xmit_drop_count(err)) {
@@ -1560,7 +1562,7 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
15601562
return err;
15611563
}
15621564

1563-
if (cl->qdisc->q.qlen == 1) {
1565+
if (first) {
15641566
if (cl->cl_flags & HFSC_RSC)
15651567
init_ed(cl, len);
15661568
if (cl->cl_flags & HFSC_FSC)

net/sched/sch_qfq.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1215,6 +1215,7 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
12151215
struct qfq_class *cl;
12161216
struct qfq_aggregate *agg;
12171217
int err = 0;
1218+
bool first;
12181219

12191220
cl = qfq_classify(skb, sch, &err);
12201221
if (cl == NULL) {
@@ -1236,6 +1237,7 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
12361237
}
12371238

12381239
gso_segs = skb_is_gso(skb) ? skb_shinfo(skb)->gso_segs : 1;
1240+
first = !cl->qdisc->q.qlen;
12391241
err = qdisc_enqueue(skb, cl->qdisc, to_free);
12401242
if (unlikely(err != NET_XMIT_SUCCESS)) {
12411243
pr_debug("qfq_enqueue: enqueue failed %d\n", err);
@@ -1253,7 +1255,7 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
12531255

12541256
agg = cl->agg;
12551257
/* if the queue was not empty, then done here */
1256-
if (cl->qdisc->q.qlen != 1) {
1258+
if (!first) {
12571259
if (unlikely(skb == cl->qdisc->ops->peek(cl->qdisc)) &&
12581260
list_first_entry(&agg->active, struct qfq_class, alist)
12591261
== cl && cl->deficit < len)

0 commit comments

Comments
 (0)