Skip to content

Commit 2ccccf5

Browse files
congwangdavem330
authored andcommitted
net_sched: update hierarchical backlog too
When the bottom qdisc decides to, for example, drop some packet, it calls qdisc_tree_decrease_qlen() to update the queue length for all its ancestors, we need to update the backlog too to keep the stats on root qdisc accurate. Cc: Jamal Hadi Salim <[email protected]> Acked-by: Jamal Hadi Salim <[email protected]> Signed-off-by: Cong Wang <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 86a7996 commit 2ccccf5

21 files changed

+91
-49
lines changed

include/net/codel.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,12 +162,14 @@ struct codel_vars {
162162
* struct codel_stats - contains codel shared variables and stats
163163
* @maxpacket: largest packet we've seen so far
164164
* @drop_count: temp count of dropped packets in dequeue()
165+
* @drop_len: bytes of dropped packets in dequeue()
165166
* ecn_mark: number of packets we ECN marked instead of dropping
166167
* ce_mark: number of packets CE marked because sojourn time was above ce_threshold
167168
*/
168169
struct codel_stats {
169170
u32 maxpacket;
170171
u32 drop_count;
172+
u32 drop_len;
171173
u32 ecn_mark;
172174
u32 ce_mark;
173175
};
@@ -308,6 +310,7 @@ static struct sk_buff *codel_dequeue(struct Qdisc *sch,
308310
vars->rec_inv_sqrt);
309311
goto end;
310312
}
313+
stats->drop_len += qdisc_pkt_len(skb);
311314
qdisc_drop(skb, sch);
312315
stats->drop_count++;
313316
skb = dequeue_func(vars, sch);
@@ -330,6 +333,7 @@ static struct sk_buff *codel_dequeue(struct Qdisc *sch,
330333
if (params->ecn && INET_ECN_set_ce(skb)) {
331334
stats->ecn_mark++;
332335
} else {
336+
stats->drop_len += qdisc_pkt_len(skb);
333337
qdisc_drop(skb, sch);
334338
stats->drop_count++;
335339

include/net/sch_generic.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,8 @@ struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue,
396396
struct Qdisc *qdisc);
397397
void qdisc_reset(struct Qdisc *qdisc);
398398
void qdisc_destroy(struct Qdisc *qdisc);
399-
void qdisc_tree_decrease_qlen(struct Qdisc *qdisc, unsigned int n);
399+
void qdisc_tree_reduce_backlog(struct Qdisc *qdisc, unsigned int n,
400+
unsigned int len);
400401
struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
401402
const struct Qdisc_ops *ops);
402403
struct Qdisc *qdisc_create_dflt(struct netdev_queue *dev_queue,
@@ -716,7 +717,7 @@ static inline struct Qdisc *qdisc_replace(struct Qdisc *sch, struct Qdisc *new,
716717
old = *pold;
717718
*pold = new;
718719
if (old != NULL) {
719-
qdisc_tree_decrease_qlen(old, old->q.qlen);
720+
qdisc_tree_reduce_backlog(old, old->q.qlen, old->qstats.backlog);
720721
qdisc_reset(old);
721722
}
722723
sch_tree_unlock(sch);

net/sched/sch_api.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -744,14 +744,15 @@ static u32 qdisc_alloc_handle(struct net_device *dev)
744744
return 0;
745745
}
746746

747-
void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n)
747+
void qdisc_tree_reduce_backlog(struct Qdisc *sch, unsigned int n,
748+
unsigned int len)
748749
{
749750
const struct Qdisc_class_ops *cops;
750751
unsigned long cl;
751752
u32 parentid;
752753
int drops;
753754

754-
if (n == 0)
755+
if (n == 0 && len == 0)
755756
return;
756757
drops = max_t(int, n, 0);
757758
rcu_read_lock();
@@ -774,11 +775,12 @@ void qdisc_tree_decrease_qlen(struct Qdisc *sch, unsigned int n)
774775
cops->put(sch, cl);
775776
}
776777
sch->q.qlen -= n;
778+
sch->qstats.backlog -= len;
777779
__qdisc_qstats_drop(sch, drops);
778780
}
779781
rcu_read_unlock();
780782
}
781-
EXPORT_SYMBOL(qdisc_tree_decrease_qlen);
783+
EXPORT_SYMBOL(qdisc_tree_reduce_backlog);
782784

783785
static void notify_and_destroy(struct net *net, struct sk_buff *skb,
784786
struct nlmsghdr *n, u32 clid,

net/sched/sch_cbq.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1909,16 +1909,17 @@ static int cbq_delete(struct Qdisc *sch, unsigned long arg)
19091909
{
19101910
struct cbq_sched_data *q = qdisc_priv(sch);
19111911
struct cbq_class *cl = (struct cbq_class *)arg;
1912-
unsigned int qlen;
1912+
unsigned int qlen, backlog;
19131913

19141914
if (cl->filters || cl->children || cl == &q->link)
19151915
return -EBUSY;
19161916

19171917
sch_tree_lock(sch);
19181918

19191919
qlen = cl->q->q.qlen;
1920+
backlog = cl->q->qstats.backlog;
19201921
qdisc_reset(cl->q);
1921-
qdisc_tree_decrease_qlen(cl->q, qlen);
1922+
qdisc_tree_reduce_backlog(cl->q, qlen, backlog);
19221923

19231924
if (cl->next_alive)
19241925
cbq_deactivate_class(cl);

net/sched/sch_choke.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,8 @@ static void choke_drop_by_idx(struct Qdisc *sch, unsigned int idx)
128128
choke_zap_tail_holes(q);
129129

130130
qdisc_qstats_backlog_dec(sch, skb);
131+
qdisc_tree_reduce_backlog(sch, 1, qdisc_pkt_len(skb));
131132
qdisc_drop(skb, sch);
132-
qdisc_tree_decrease_qlen(sch, 1);
133133
--sch->q.qlen;
134134
}
135135

@@ -456,6 +456,7 @@ static int choke_change(struct Qdisc *sch, struct nlattr *opt)
456456
old = q->tab;
457457
if (old) {
458458
unsigned int oqlen = sch->q.qlen, tail = 0;
459+
unsigned dropped = 0;
459460

460461
while (q->head != q->tail) {
461462
struct sk_buff *skb = q->tab[q->head];
@@ -467,11 +468,12 @@ static int choke_change(struct Qdisc *sch, struct nlattr *opt)
467468
ntab[tail++] = skb;
468469
continue;
469470
}
471+
dropped += qdisc_pkt_len(skb);
470472
qdisc_qstats_backlog_dec(sch, skb);
471473
--sch->q.qlen;
472474
qdisc_drop(skb, sch);
473475
}
474-
qdisc_tree_decrease_qlen(sch, oqlen - sch->q.qlen);
476+
qdisc_tree_reduce_backlog(sch, oqlen - sch->q.qlen, dropped);
475477
q->head = 0;
476478
q->tail = tail;
477479
}

net/sched/sch_codel.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,13 @@ static struct sk_buff *codel_qdisc_dequeue(struct Qdisc *sch)
7979

8080
skb = codel_dequeue(sch, &q->params, &q->vars, &q->stats, dequeue);
8181

82-
/* We cant call qdisc_tree_decrease_qlen() if our qlen is 0,
82+
/* We cant call qdisc_tree_reduce_backlog() if our qlen is 0,
8383
* or HTB crashes. Defer it for next round.
8484
*/
8585
if (q->stats.drop_count && sch->q.qlen) {
86-
qdisc_tree_decrease_qlen(sch, q->stats.drop_count);
86+
qdisc_tree_reduce_backlog(sch, q->stats.drop_count, q->stats.drop_len);
8787
q->stats.drop_count = 0;
88+
q->stats.drop_len = 0;
8889
}
8990
if (skb)
9091
qdisc_bstats_update(sch, skb);
@@ -116,7 +117,7 @@ static int codel_change(struct Qdisc *sch, struct nlattr *opt)
116117
{
117118
struct codel_sched_data *q = qdisc_priv(sch);
118119
struct nlattr *tb[TCA_CODEL_MAX + 1];
119-
unsigned int qlen;
120+
unsigned int qlen, dropped = 0;
120121
int err;
121122

122123
if (!opt)
@@ -156,10 +157,11 @@ static int codel_change(struct Qdisc *sch, struct nlattr *opt)
156157
while (sch->q.qlen > sch->limit) {
157158
struct sk_buff *skb = __skb_dequeue(&sch->q);
158159

160+
dropped += qdisc_pkt_len(skb);
159161
qdisc_qstats_backlog_dec(sch, skb);
160162
qdisc_drop(skb, sch);
161163
}
162-
qdisc_tree_decrease_qlen(sch, qlen - sch->q.qlen);
164+
qdisc_tree_reduce_backlog(sch, qlen - sch->q.qlen, dropped);
163165

164166
sch_tree_unlock(sch);
165167
return 0;

net/sched/sch_drr.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,10 @@ static struct drr_class *drr_find_class(struct Qdisc *sch, u32 classid)
5353
static void drr_purge_queue(struct drr_class *cl)
5454
{
5555
unsigned int len = cl->qdisc->q.qlen;
56+
unsigned int backlog = cl->qdisc->qstats.backlog;
5657

5758
qdisc_reset(cl->qdisc);
58-
qdisc_tree_decrease_qlen(cl->qdisc, len);
59+
qdisc_tree_reduce_backlog(cl->qdisc, len, backlog);
5960
}
6061

6162
static const struct nla_policy drr_policy[TCA_DRR_MAX + 1] = {

net/sched/sch_fq.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,7 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt)
662662
struct fq_sched_data *q = qdisc_priv(sch);
663663
struct nlattr *tb[TCA_FQ_MAX + 1];
664664
int err, drop_count = 0;
665+
unsigned drop_len = 0;
665666
u32 fq_log;
666667

667668
if (!opt)
@@ -736,10 +737,11 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt)
736737

737738
if (!skb)
738739
break;
740+
drop_len += qdisc_pkt_len(skb);
739741
kfree_skb(skb);
740742
drop_count++;
741743
}
742-
qdisc_tree_decrease_qlen(sch, drop_count);
744+
qdisc_tree_reduce_backlog(sch, drop_count, drop_len);
743745

744746
sch_tree_unlock(sch);
745747
return err;

net/sched/sch_fq_codel.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ static unsigned int fq_codel_qdisc_drop(struct Qdisc *sch)
175175
static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch)
176176
{
177177
struct fq_codel_sched_data *q = qdisc_priv(sch);
178-
unsigned int idx;
178+
unsigned int idx, prev_backlog;
179179
struct fq_codel_flow *flow;
180180
int uninitialized_var(ret);
181181

@@ -203,6 +203,7 @@ static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch)
203203
if (++sch->q.qlen <= sch->limit)
204204
return NET_XMIT_SUCCESS;
205205

206+
prev_backlog = sch->qstats.backlog;
206207
q->drop_overlimit++;
207208
/* Return Congestion Notification only if we dropped a packet
208209
* from this flow.
@@ -211,7 +212,7 @@ static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch)
211212
return NET_XMIT_CN;
212213

213214
/* As we dropped a packet, better let upper stack know this */
214-
qdisc_tree_decrease_qlen(sch, 1);
215+
qdisc_tree_reduce_backlog(sch, 1, prev_backlog - sch->qstats.backlog);
215216
return NET_XMIT_SUCCESS;
216217
}
217218

@@ -241,6 +242,7 @@ static struct sk_buff *fq_codel_dequeue(struct Qdisc *sch)
241242
struct fq_codel_flow *flow;
242243
struct list_head *head;
243244
u32 prev_drop_count, prev_ecn_mark;
245+
unsigned int prev_backlog;
244246

245247
begin:
246248
head = &q->new_flows;
@@ -259,6 +261,7 @@ static struct sk_buff *fq_codel_dequeue(struct Qdisc *sch)
259261

260262
prev_drop_count = q->cstats.drop_count;
261263
prev_ecn_mark = q->cstats.ecn_mark;
264+
prev_backlog = sch->qstats.backlog;
262265

263266
skb = codel_dequeue(sch, &q->cparams, &flow->cvars, &q->cstats,
264267
dequeue);
@@ -276,12 +279,14 @@ static struct sk_buff *fq_codel_dequeue(struct Qdisc *sch)
276279
}
277280
qdisc_bstats_update(sch, skb);
278281
flow->deficit -= qdisc_pkt_len(skb);
279-
/* We cant call qdisc_tree_decrease_qlen() if our qlen is 0,
282+
/* We cant call qdisc_tree_reduce_backlog() if our qlen is 0,
280283
* or HTB crashes. Defer it for next round.
281284
*/
282285
if (q->cstats.drop_count && sch->q.qlen) {
283-
qdisc_tree_decrease_qlen(sch, q->cstats.drop_count);
286+
qdisc_tree_reduce_backlog(sch, q->cstats.drop_count,
287+
q->cstats.drop_len);
284288
q->cstats.drop_count = 0;
289+
q->cstats.drop_len = 0;
285290
}
286291
return skb;
287292
}
@@ -372,11 +377,13 @@ static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt)
372377
while (sch->q.qlen > sch->limit) {
373378
struct sk_buff *skb = fq_codel_dequeue(sch);
374379

380+
q->cstats.drop_len += qdisc_pkt_len(skb);
375381
kfree_skb(skb);
376382
q->cstats.drop_count++;
377383
}
378-
qdisc_tree_decrease_qlen(sch, q->cstats.drop_count);
384+
qdisc_tree_reduce_backlog(sch, q->cstats.drop_count, q->cstats.drop_len);
379385
q->cstats.drop_count = 0;
386+
q->cstats.drop_len = 0;
380387

381388
sch_tree_unlock(sch);
382389
return 0;

net/sched/sch_hfsc.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -895,9 +895,10 @@ static void
895895
hfsc_purge_queue(struct Qdisc *sch, struct hfsc_class *cl)
896896
{
897897
unsigned int len = cl->qdisc->q.qlen;
898+
unsigned int backlog = cl->qdisc->qstats.backlog;
898899

899900
qdisc_reset(cl->qdisc);
900-
qdisc_tree_decrease_qlen(cl->qdisc, len);
901+
qdisc_tree_reduce_backlog(cl->qdisc, len, backlog);
901902
}
902903

903904
static void

0 commit comments

Comments
 (0)