Skip to content

Commit 9190b3b

Browse files
Eric Dumazetdavem330
Eric Dumazet
authored andcommitted
net_sched: accurate bytes/packets stats/rates
In commit 44b8288 (net_sched: pfifo_head_drop problem), we fixed a problem with pfifo_head drops that incorrectly decreased sch->bstats.bytes and sch->bstats.packets Several qdiscs (CHOKe, SFQ, pfifo_head, ...) are able to drop a previously enqueued packet, and bstats cannot be changed, so bstats/rates are not accurate (over estimated) This patch changes the qdisc_bstats updates to be done at dequeue() time instead of enqueue() time. bstats counters no longer account for dropped frames, and rates are more correct, since enqueue() bursts dont have effect on dequeue() rate. Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Acked-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent b305325 commit 9190b3b

File tree

14 files changed

+29
-33
lines changed

14 files changed

+29
-33
lines changed

include/net/sch_generic.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,6 @@ static inline int __qdisc_enqueue_tail(struct sk_buff *skb, struct Qdisc *sch,
445445
{
446446
__skb_queue_tail(list, skb);
447447
sch->qstats.backlog += qdisc_pkt_len(skb);
448-
qdisc_bstats_update(sch, skb);
449448

450449
return NET_XMIT_SUCCESS;
451450
}
@@ -460,8 +459,10 @@ static inline struct sk_buff *__qdisc_dequeue_head(struct Qdisc *sch,
460459
{
461460
struct sk_buff *skb = __skb_dequeue(list);
462461

463-
if (likely(skb != NULL))
462+
if (likely(skb != NULL)) {
464463
sch->qstats.backlog -= qdisc_pkt_len(skb);
464+
qdisc_bstats_update(sch, skb);
465+
}
465466

466467
return skb;
467468
}
@@ -474,10 +475,11 @@ static inline struct sk_buff *qdisc_dequeue_head(struct Qdisc *sch)
474475
static inline unsigned int __qdisc_queue_drop_head(struct Qdisc *sch,
475476
struct sk_buff_head *list)
476477
{
477-
struct sk_buff *skb = __qdisc_dequeue_head(sch, list);
478+
struct sk_buff *skb = __skb_dequeue(list);
478479

479480
if (likely(skb != NULL)) {
480481
unsigned int len = qdisc_pkt_len(skb);
482+
sch->qstats.backlog -= len;
481483
kfree_skb(skb);
482484
return len;
483485
}

net/sched/sch_cbq.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,6 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
390390
ret = qdisc_enqueue(skb, cl->q);
391391
if (ret == NET_XMIT_SUCCESS) {
392392
sch->q.qlen++;
393-
qdisc_bstats_update(sch, skb);
394393
cbq_mark_toplevel(q, cl);
395394
if (!cl->next_alive)
396395
cbq_activate_class(cl);
@@ -649,7 +648,6 @@ static int cbq_reshape_fail(struct sk_buff *skb, struct Qdisc *child)
649648
ret = qdisc_enqueue(skb, cl->q);
650649
if (ret == NET_XMIT_SUCCESS) {
651650
sch->q.qlen++;
652-
qdisc_bstats_update(sch, skb);
653651
if (!cl->next_alive)
654652
cbq_activate_class(cl);
655653
return 0;
@@ -971,6 +969,7 @@ cbq_dequeue(struct Qdisc *sch)
971969

972970
skb = cbq_dequeue_1(sch);
973971
if (skb) {
972+
qdisc_bstats_update(sch, skb);
974973
sch->q.qlen--;
975974
sch->flags &= ~TCQ_F_THROTTLED;
976975
return skb;

net/sched/sch_drr.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,6 @@ static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch)
376376
}
377377

378378
bstats_update(&cl->bstats, skb);
379-
qdisc_bstats_update(sch, skb);
380379

381380
sch->q.qlen++;
382381
return err;
@@ -403,6 +402,7 @@ static struct sk_buff *drr_dequeue(struct Qdisc *sch)
403402
skb = qdisc_dequeue_peeked(cl->qdisc);
404403
if (cl->qdisc->q.qlen == 0)
405404
list_del(&cl->alist);
405+
qdisc_bstats_update(sch, skb);
406406
sch->q.qlen--;
407407
return skb;
408408
}

net/sched/sch_dsmark.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,6 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch)
260260
return err;
261261
}
262262

263-
qdisc_bstats_update(sch, skb);
264263
sch->q.qlen++;
265264

266265
return NET_XMIT_SUCCESS;
@@ -283,6 +282,7 @@ static struct sk_buff *dsmark_dequeue(struct Qdisc *sch)
283282
if (skb == NULL)
284283
return NULL;
285284

285+
qdisc_bstats_update(sch, skb);
286286
sch->q.qlen--;
287287

288288
index = skb->tc_index & (p->indices - 1);

net/sched/sch_fifo.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,14 @@ static int pfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch)
4646

4747
static int pfifo_tail_enqueue(struct sk_buff *skb, struct Qdisc* sch)
4848
{
49-
struct sk_buff *skb_head;
5049
struct fifo_sched_data *q = qdisc_priv(sch);
5150

5251
if (likely(skb_queue_len(&sch->q) < q->limit))
5352
return qdisc_enqueue_tail(skb, sch);
5453

5554
/* queue full, remove one skb to fulfill the limit */
56-
skb_head = qdisc_dequeue_head(sch);
55+
__qdisc_queue_drop_head(sch, &sch->q);
5756
sch->qstats.drops++;
58-
kfree_skb(skb_head);
59-
6057
qdisc_enqueue_tail(skb, sch);
6158

6259
return NET_XMIT_CN;

net/sched/sch_hfsc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1600,7 +1600,6 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
16001600
set_active(cl, qdisc_pkt_len(skb));
16011601

16021602
bstats_update(&cl->bstats, skb);
1603-
qdisc_bstats_update(sch, skb);
16041603
sch->q.qlen++;
16051604

16061605
return NET_XMIT_SUCCESS;
@@ -1666,6 +1665,7 @@ hfsc_dequeue(struct Qdisc *sch)
16661665
}
16671666

16681667
sch->flags &= ~TCQ_F_THROTTLED;
1668+
qdisc_bstats_update(sch, skb);
16691669
sch->q.qlen--;
16701670

16711671
return skb;

net/sched/sch_htb.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,6 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
574574
}
575575

576576
sch->q.qlen++;
577-
qdisc_bstats_update(sch, skb);
578577
return NET_XMIT_SUCCESS;
579578
}
580579

@@ -842,7 +841,7 @@ static struct sk_buff *htb_dequeue_tree(struct htb_sched *q, int prio,
842841

843842
static struct sk_buff *htb_dequeue(struct Qdisc *sch)
844843
{
845-
struct sk_buff *skb = NULL;
844+
struct sk_buff *skb;
846845
struct htb_sched *q = qdisc_priv(sch);
847846
int level;
848847
psched_time_t next_event;
@@ -851,6 +850,8 @@ static struct sk_buff *htb_dequeue(struct Qdisc *sch)
851850
/* try to dequeue direct packets as high prio (!) to minimize cpu work */
852851
skb = __skb_dequeue(&q->direct_queue);
853852
if (skb != NULL) {
853+
ok:
854+
qdisc_bstats_update(sch, skb);
854855
sch->flags &= ~TCQ_F_THROTTLED;
855856
sch->q.qlen--;
856857
return skb;
@@ -884,11 +885,8 @@ static struct sk_buff *htb_dequeue(struct Qdisc *sch)
884885
int prio = ffz(m);
885886
m |= 1 << prio;
886887
skb = htb_dequeue_tree(q, prio, level);
887-
if (likely(skb != NULL)) {
888-
sch->q.qlen--;
889-
sch->flags &= ~TCQ_F_THROTTLED;
890-
goto fin;
891-
}
888+
if (likely(skb != NULL))
889+
goto ok;
892890
}
893891
}
894892
sch->qstats.overlimits++;

net/sched/sch_multiq.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ multiq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
8383

8484
ret = qdisc_enqueue(skb, qdisc);
8585
if (ret == NET_XMIT_SUCCESS) {
86-
qdisc_bstats_update(sch, skb);
8786
sch->q.qlen++;
8887
return NET_XMIT_SUCCESS;
8988
}
@@ -112,6 +111,7 @@ static struct sk_buff *multiq_dequeue(struct Qdisc *sch)
112111
qdisc = q->queues[q->curband];
113112
skb = qdisc->dequeue(qdisc);
114113
if (skb) {
114+
qdisc_bstats_update(sch, skb);
115115
sch->q.qlen--;
116116
return skb;
117117
}

net/sched/sch_netem.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,6 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
240240

241241
if (likely(ret == NET_XMIT_SUCCESS)) {
242242
sch->q.qlen++;
243-
qdisc_bstats_update(sch, skb);
244243
} else if (net_xmit_drop_count(ret)) {
245244
sch->qstats.drops++;
246245
}
@@ -289,6 +288,7 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)
289288
skb->tstamp.tv64 = 0;
290289
#endif
291290
pr_debug("netem_dequeue: return skb=%p\n", skb);
291+
qdisc_bstats_update(sch, skb);
292292
sch->q.qlen--;
293293
return skb;
294294
}
@@ -476,7 +476,6 @@ static int tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)
476476
__skb_queue_after(list, skb, nskb);
477477

478478
sch->qstats.backlog += qdisc_pkt_len(nskb);
479-
qdisc_bstats_update(sch, nskb);
480479

481480
return NET_XMIT_SUCCESS;
482481
}

net/sched/sch_prio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ prio_enqueue(struct sk_buff *skb, struct Qdisc *sch)
8484

8585
ret = qdisc_enqueue(skb, qdisc);
8686
if (ret == NET_XMIT_SUCCESS) {
87-
qdisc_bstats_update(sch, skb);
8887
sch->q.qlen++;
8988
return NET_XMIT_SUCCESS;
9089
}
@@ -116,6 +115,7 @@ static struct sk_buff *prio_dequeue(struct Qdisc* sch)
116115
struct Qdisc *qdisc = q->queues[prio];
117116
struct sk_buff *skb = qdisc->dequeue(qdisc);
118117
if (skb) {
118+
qdisc_bstats_update(sch, skb);
119119
sch->q.qlen--;
120120
return skb;
121121
}

net/sched/sch_red.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@ static int red_enqueue(struct sk_buff *skb, struct Qdisc* sch)
9494

9595
ret = qdisc_enqueue(skb, child);
9696
if (likely(ret == NET_XMIT_SUCCESS)) {
97-
qdisc_bstats_update(sch, skb);
9897
sch->q.qlen++;
9998
} else if (net_xmit_drop_count(ret)) {
10099
q->stats.pdrop++;
@@ -114,11 +113,13 @@ static struct sk_buff * red_dequeue(struct Qdisc* sch)
114113
struct Qdisc *child = q->qdisc;
115114

116115
skb = child->dequeue(child);
117-
if (skb)
116+
if (skb) {
117+
qdisc_bstats_update(sch, skb);
118118
sch->q.qlen--;
119-
else if (!red_is_idling(&q->parms))
120-
red_start_of_idle_period(&q->parms);
121-
119+
} else {
120+
if (!red_is_idling(&q->parms))
121+
red_start_of_idle_period(&q->parms);
122+
}
122123
return skb;
123124
}
124125

net/sched/sch_sfq.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -402,10 +402,8 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
402402
q->tail = slot;
403403
slot->allot = q->scaled_quantum;
404404
}
405-
if (++sch->q.qlen <= q->limit) {
406-
qdisc_bstats_update(sch, skb);
405+
if (++sch->q.qlen <= q->limit)
407406
return NET_XMIT_SUCCESS;
408-
}
409407

410408
sfq_drop(sch);
411409
return NET_XMIT_CN;
@@ -445,6 +443,7 @@ sfq_dequeue(struct Qdisc *sch)
445443
}
446444
skb = slot_dequeue_head(slot);
447445
sfq_dec(q, a);
446+
qdisc_bstats_update(sch, skb);
448447
sch->q.qlen--;
449448
sch->qstats.backlog -= qdisc_pkt_len(skb);
450449

net/sched/sch_tbf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,6 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch)
134134
}
135135

136136
sch->q.qlen++;
137-
qdisc_bstats_update(sch, skb);
138137
return NET_XMIT_SUCCESS;
139138
}
140139

@@ -187,6 +186,7 @@ static struct sk_buff *tbf_dequeue(struct Qdisc* sch)
187186
q->ptokens = ptoks;
188187
sch->q.qlen--;
189188
sch->flags &= ~TCQ_F_THROTTLED;
189+
qdisc_bstats_update(sch, skb);
190190
return skb;
191191
}
192192

net/sched/sch_teql.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ teql_enqueue(struct sk_buff *skb, struct Qdisc* sch)
8787

8888
if (q->q.qlen < dev->tx_queue_len) {
8989
__skb_queue_tail(&q->q, skb);
90-
qdisc_bstats_update(sch, skb);
9190
return NET_XMIT_SUCCESS;
9291
}
9392

@@ -111,6 +110,8 @@ teql_dequeue(struct Qdisc* sch)
111110
dat->m->slaves = sch;
112111
netif_wake_queue(m);
113112
}
113+
} else {
114+
qdisc_bstats_update(sch, skb);
114115
}
115116
sch->q.qlen = dat->q.qlen + dat_queue->qdisc->q.qlen;
116117
return skb;

0 commit comments

Comments
 (0)