: pkt_sched.h cleanup + misc changes
Subsystems (4)
cover : pkt_sched.h cleanup + misc changes
These patches fix an off-by-one in netem, clean up pkt_sched.h by removing most of the now unnecessary PSCHED time macros and turning the two remaining ones into inline functions, consolidate some common filter destruction code and move the TCQ_F_THROTTLED optimization from netem to qdisc_restart.
Please apply, thanks.
include/net/pkt_sched.h | 24 +++++++------- include/net/red.h | 10 +++--- include/net/sch_generic.h | 10 +----- net/sched/act_police.c | 17 ++++------ net/sched/sch_api.c | 20 ++++++++++-- net/sched/sch_atm.c | 17 +--------- net/sched/sch_cbq.c | 76 ++++++++++++++++++---------------------------- net/sched/sch_dsmark.c | 8 ---- net/sched/sch_generic.c | 4 ++ net/sched/sch_hfsc.c | 23 +++---------- net/sched/sch_htb.c | 24 ++++---------- net/sched/sch_ingress.c | 7 ---- net/sched/sch_netem.c | 24 +++++--------- net/sched/sch_prio.c | 7 ---- net/sched/sch_tbf.c | 9 ++--- 15 files changed, 110 insertions(+), 170 deletions(-)
Patrick McHardy (11):
[NET_SCHED]: sch_netem: fix off-by-one in send time comparison [NET_SCHED]: kill PSCHED_AUDIT_TDIFF
[NET_SCHED]: kill PSCHED_TADD/PSCHED_TADD2 [NET_SCHED]: kill PSCHED_TLESS
[NET_SCHED]: kill PSCHED_SET_PASTPERFECT/PSCHED_IS_PASTPERFECT [NET_SCHED]: kill PSCHED_TDIFF
[NET_SCHED]: turn PSCHED_TDIFF_SAFE into inline function [NET_SCHED]: turn PSCHED_GET_TIME into inline function [NET_SCHED]: Unline tcf_destroy
[NET_SCHED]: qdisc: remove unnecessary memory barriers [NET_SCHED]: qdisc: avoid dequeue while throttled
PATCH 1/11 : sch_netem: fix off-by-one in send time comparison
[NET_SCHED]: sch_netem: fix off-by-one in send time comparison
netem checks PSCHED_TLESS(cb->time_to_send, now) to find out whether it is allowed to send a packet, which is equivalent to cb->time_to_send < now. Use !PSCHED_TLESS(now, cb->time_to_send) instead to properly handle cb->time_to_send == now.
---
commit 9f8c07452088f432c79ac3a8d87d6adebcce57df
tree 42b214f74b8b2d5bd3065e9f63d8048beb4f3bdc
parent 3231f075945001667eafaf325abab8c992b3d1e4
author Patrick McHardy <[email protected]> Thu, 22 Mar 2007 23:57:32 +0100 committer Patrick McHardy <[email protected]> Fri, 23 Mar 2007 10:31:26 +0100
net/sched/sch_netem.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
net/sched/sch_netem.c +1 -1
@@ -286,7 +286,7 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)/* if more time remaining? */ PSCHED_GET_TIME (now); -if (PSCHED_TLESS (cb->time_to_send, now)) { +if (!PSCHED_TLESS (now, cb->time_to_send)) {pr_debug ("netem_dequeue: return skb=%p\n" , skb); sch->q.qlen--;return skb;
Re: [NET_SCHED 01/11]: sch_netem: fix off-by-one in send time comparison
Quoted 9 lines · On Fri, 23 Mar 2007 14:35:40 +0100 (MET) Patrick McHardy <[email protected]>…
[
NET_SCHED]:sch_netem: fix off-by-one in send time comparisonnetem checks
PSCHED_TLESS(cb->time_to_send, now)to find out whether it is allowed to send a packet, which is equivalent tocb->time_to_send< now. Use !PSCHED_TLESS(now,cb->time_to_send) instead to properly handlecb->time_to_send== now.Signed-off-by Patrick McHardy <[email protected]>
Thanks, I saw that earlier in another spot and fixed it.
Signature · 1 line
Stephen Hemminger <[email protected]>
PATCH 2/11 : kill PSCHED_AUDIT_TDIFF
In reply to Patrick McHardy[NET_SCHED]: kill PSCHED_AUDIT_TDIFF
---
commit 4a4a3d59dca71f202ab063b909c84c96c8ea09a7
tree 4958bfec571a3330bd023ebe50f7b071f6dc7dd7
parent 9f8c07452088f432c79ac3a8d87d6adebcce57df
author Patrick McHardy <[email protected]> Thu, 22 Mar 2007 23:58:12 +0100 committer Patrick McHardy <[email protected]> Fri, 23 Mar 2007 10:31:27 +0100
include/net/pkt_sched.h | 1 - net/sched/sch_cbq.c | 2 -- 2 files changed, 0 insertions(+), 3 deletions(-)
include/net/pkt_sched.h +0 -1
@@ -59,7 +59,6 @@ typedef long psched_tdiff_t;#define PSCHED_TADD (tv, delta) ((tv) += (delta))#define PSCHED_SET_PASTPERFECT (t) ((t) = 0)#define PSCHED_IS_PASTPERFECT (t) ((t) == 0) -#define PSCHED_AUDIT_TDIFF (t)struct qdisc_watchdog {struct hrtimer timer;
net/sched/sch_cbq.c +0 -2
@@ -820,8 +820,6 @@ cbq_update(struct cbq_sched_data *q) idle -=L2T (&q->link, len); idle +=L2T (cl, len); -PSCHED_AUDIT_TDIFF (idle); -PSCHED_TADD2 (q->now, idle, cl->undertime); }else {/* Underlimit */
PATCH 3/11 : kill PSCHED_TADD/PSCHED_TADD2
In reply to Patrick McHardy[NET_SCHED]: kill PSCHED_TADD/PSCHED_TADD2
---
commit 145a1a6010c6b852ffab28c110d8911a6161aa8b
tree 84b7bf284ea3b870a9b5fd9dae3adaad9979dc26
parent 4a4a3d59dca71f202ab063b909c84c96c8ea09a7
author Patrick McHardy <[email protected]> Thu, 22 Mar 2007 23:58:42 +0100 committer Patrick McHardy <[email protected]> Fri, 23 Mar 2007 10:31:27 +0100
include/net/pkt_sched.h | 2 -- net/sched/sch_cbq.c | 12 ++++++------ net/sched/sch_netem.c | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-)
include/net/pkt_sched.h +0 -2
@@ -55,8 +55,6 @@ typedef long psched_tdiff_t;#define PSCHED_TDIFF_SAFE (tv1, tv2, bound) \ min_t(long long, (tv1) - (tv2), bound)#define PSCHED_TLESS (tv1, tv2) ((tv1) < (tv2)) -#define PSCHED_TADD2 (tv, delta, tv_res) ((tv_res) = (tv) + (delta)) -#define PSCHED_TADD (tv, delta) ((tv) += (delta))#define PSCHED_SET_PASTPERFECT (t) ((t) = 0)#define PSCHED_IS_PASTPERFECT (t) ((t) == 0)
net/sched/sch_cbq.c +6 -6
@@ -387,7 +387,7 @@ cbq_mark_toplevel(struct cbq_sched_data *q, struct cbq_class *cl)PSCHED_GET_TIME (now); incr =PSCHED_TDIFF (now, q->now_rt); -PSCHED_TADD2 (q->now, incr, now); + now = q->now + incr; do { if (PSCHED_TLESS(cl->undertime, now)) {
@@ -492,7 +492,7 @@ static void cbq_ovl_classic(struct cbq_class *cl) cl->avgidle = cl->minidle;if (delay <=0 ) delay =1 ; -PSCHED_TADD2 (q->now, delay, cl->undertime); + cl->undertime = q->now + delay; cl->xstats.overactions++; cl->delayed =1 ;
@@ -558,7 +558,7 @@ static void cbq_ovl_delay(struct cbq_class *cl) delay -= (-cl->avgidle) - ((-cl->avgidle) >> cl->ewma_log);if (cl->avgidle < cl->minidle) cl->avgidle = cl->minidle; -PSCHED_TADD2 (q->now, delay, cl->undertime); + cl->undertime = q->now + delay;if (delay >0 ) { sched += delay + cl->penalty;
@@ -820,7 +820,7 @@ cbq_update(struct cbq_sched_data *q) idle -=L2T (&q->link, len); idle +=L2T (cl, len); -PSCHED_TADD2 (q->now, idle, cl->undertime); + cl->undertime = q->now + idle; }else {/* Underlimit */
@@ -1018,12 +1018,12 @@ cbq_dequeue(struct Qdisc *sch)cbq_time = max(real_time, work); */ incr2 =L2T (&q->link, q->tx_len); -PSCHED_TADD (q->now, incr2); + q->now += incr2;cbq_update (q);if ((incr -= incr2) <0 ) incr =0 ; } -PSCHED_TADD (q->now, incr); + q->now += incr; q->now_rt = now;for (;;) {
net/sched/sch_netem.c +1 -1
@@ -218,7 +218,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) &q->delay_cor, q->delay_dist);PSCHED_GET_TIME (now); -PSCHED_TADD2 (now, delay, cb->time_to_send); + cb->time_to_send = now + delay; ++q->counter; ret = q->qdisc->enqueue (skb, q->qdisc); }else {
PATCH 4/11 : kill PSCHED_TLESS
In reply to Patrick McHardy[NET_SCHED]: kill PSCHED_TLESS
---
commit 4f8fc418f88c0b7ee6e726b05f27c42d8e20593c
tree c70508f2e0174aef42aaf99bf0cef4184d7ed07e
parent 145a1a6010c6b852ffab28c110d8911a6161aa8b
author Patrick McHardy <[email protected]> Fri, 23 Mar 2007 00:00:55 +0100 committer Patrick McHardy <[email protected]> Fri, 23 Mar 2007 10:31:28 +0100
include/net/pkt_sched.h | 1 - net/sched/sch_cbq.c | 7 +++---- net/sched/sch_netem.c | 6 +++--- 3 files changed, 6 insertions(+), 8 deletions(-)
include/net/pkt_sched.h +0 -1
@@ -54,7 +54,6 @@ typedef long psched_tdiff_t;#define PSCHED_TDIFF (tv1, tv2) (long)((tv1) - (tv2))#define PSCHED_TDIFF_SAFE (tv1, tv2, bound) \ min_t(long long, (tv1) - (tv2), bound) -#define PSCHED_TLESS (tv1, tv2) ((tv1) < (tv2))#define PSCHED_SET_PASTPERFECT (t) ((t) = 0)#define PSCHED_IS_PASTPERFECT (t) ((t) == 0)
net/sched/sch_cbq.c +3 -4
@@ -390,7 +390,7 @@ cbq_mark_toplevel(struct cbq_sched_data *q, struct cbq_class *cl) now = q->now + incr; do { - if (PSCHED_TLESS(cl->undertime, now)) { + if (cl->undertime < now) { q->toplevel = cl->level; return; }
@@ -845,8 +845,7 @@ cbq_under_limit(struct cbq_class *cl)if (cl->tparent ==NULL )return cl; -if (PSCHED_IS_PASTPERFECT (cl->undertime) || - !PSCHED_TLESS (q->now, cl->undertime)) { +if (PSCHED_IS_PASTPERFECT (cl->undertime) || q->now >= cl->undertime) { cl->delayed =0 ;return cl; }
@@ -870,7 +869,7 @@ cbq_under_limit(struct cbq_class *cl)if (cl->level > q->toplevel)return NULL ; }while (!PSCHED_IS_PASTPERFECT (cl->undertime) && -PSCHED_TLESS (q->now, cl->undertime)); + q->now < cl->undertime); cl->delayed =0 ;return cl;
net/sched/sch_netem.c +3 -3
@@ -286,7 +286,7 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)/* if more time remaining? */ PSCHED_GET_TIME (now); -if (!PSCHED_TLESS (now, cb->time_to_send)) { +if (cb->time_to_send <= now) {pr_debug ("netem_dequeue: return skb=%p\n" , skb); sch->q.qlen--;return skb;
@@ -494,7 +494,7 @@ static int tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)if (likely (skb_queue_len (list) < q->limit)) {/* Optimize for add at tail */ -if (likely (skb_queue_empty (list) || !PSCHED_TLESS (tnext, q->oldest))) { +if (likely (skb_queue_empty (list) || tnext >= q->oldest)) { q->oldest = tnext;return qdisc_enqueue_tail (nskb, sch); }
@@ -503,7 +503,7 @@ static int tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)const struct netem_skb_cb *cb = (const struct netem_skb_cb *)skb->cb; -if (!PSCHED_TLESS (tnext, cb->time_to_send)) +if (tnext >= cb->time_to_send)break ; }
PATCH 5/11 : kill PSCHED_SET_PASTPERFECT/PSCHED_IS_PASTPERFECT
In reply to Patrick McHardy[NET_SCHED]: kill PSCHED_SET_PASTPERFECT/PSCHED_IS_PASTPERFECT
Use direct assignment and comparison instead.
---
commit ec252ac5640ea38d3630cdb97333c398a75391b9
tree bce7b2c63ffb0694942484418f1adf08ed78292d
parent 4f8fc418f88c0b7ee6e726b05f27c42d8e20593c
author Patrick McHardy <[email protected]> Fri, 23 Mar 2007 00:01:32 +0100 committer Patrick McHardy <[email protected]> Fri, 23 Mar 2007 10:31:29 +0100
include/net/pkt_sched.h | 3 +-- include/net/red.h | 4 ++-- net/sched/sch_cbq.c | 17 ++++++++--------- net/sched/sch_netem.c | 2 +- 4 files changed, 12 insertions(+), 14 deletions(-)
include/net/pkt_sched.h +1 -2
@@ -54,8 +54,7 @@ typedef long psched_tdiff_t;#define PSCHED_TDIFF (tv1, tv2) (long)((tv1) - (tv2))#define PSCHED_TDIFF_SAFE (tv1, tv2, bound) \ min_t(long long, (tv1) - (tv2), bound) -#define PSCHED_SET_PASTPERFECT (t) ((t) = 0) -#define PSCHED_IS_PASTPERFECT (t) ((t) == 0) +#define PSCHED_PASTPERFECT 0struct qdisc_watchdog {struct hrtimer timer;
include/net/red.h +2 -2
@@ -151,7 +151,7 @@ static inline void red_set_parms(struct red_parms *p,static inline int red_is_idling (struct red_parms *p) { -return !PSCHED_IS_PASTPERFECT (p->qidlestart); +return p->qidlestart !=PSCHED_PASTPERFECT ; }static inline void red_start_of_idle_period (struct red_parms *p)
@@ -161,7 +161,7 @@ static inline void red_start_of_idle_period(struct red_parms *p)static inline void red_end_of_idle_period (struct red_parms *p) { -PSCHED_SET_PASTPERFECT (p->qidlestart); + p->qidlestart =PSCHED_PASTPERFECT ; }static inline void red_restart (struct red_parms *p)
net/sched/sch_cbq.c +8 -9
@@ -738,7 +738,7 @@ cbq_update_toplevel(struct cbq_sched_data *q, struct cbq_class *cl,if (cl && q->toplevel >= borrowed->level) {if (cl->q->q.qlen >1 ) { do { - if (PSCHED_IS_PASTPERFECT(borrowed->undertime)) { + if (borrowed->undertime == PSCHED_PASTPERFECT) { q->toplevel = borrowed->level; return; }
@@ -824,7 +824,7 @@ cbq_update(struct cbq_sched_data *q) }else {/* Underlimit */ -PSCHED_SET_PASTPERFECT (cl->undertime); + cl->undertime =PSCHED_PASTPERFECT ;if (avgidle > cl->maxidle) cl->avgidle = cl->maxidle;else
@@ -845,7 +845,7 @@ cbq_under_limit(struct cbq_class *cl)if (cl->tparent ==NULL )return cl; -if (PSCHED_IS_PASTPERFECT (cl->undertime) || q->now >= cl->undertime) { +if (cl->undertime ==PSCHED_PASTPERFECT || q->now >= cl->undertime) { cl->delayed =0 ;return cl; }
@@ -868,8 +868,7 @@ cbq_under_limit(struct cbq_class *cl) }if (cl->level > q->toplevel)return NULL ; - }while (!PSCHED_IS_PASTPERFECT (cl->undertime) && - q->now < cl->undertime); + }while (cl->undertime !=PSCHED_PASTPERFECT && q->now < cl->undertime); cl->delayed =0 ;return cl;
@@ -1054,11 +1053,11 @@ cbq_dequeue(struct Qdisc *sch)*/ if (q->toplevel ==TC_CBQ_MAXLEVEL && -PSCHED_IS_PASTPERFECT (q->link.undertime)) + q->link.undertime ==PSCHED_PASTPERFECT )break ; q->toplevel =TC_CBQ_MAXLEVEL ; -PSCHED_SET_PASTPERFECT (q->link.undertime); + q->link.undertime =PSCHED_PASTPERFECT ; }/* No packets in scheduler or nobody wants to give them to us :-(
@@ -1289,7 +1288,7 @@ cbq_reset(struct Qdisc* sch)qdisc_reset (cl->q); cl->next_alive =NULL ; -PSCHED_SET_PASTPERFECT (cl->undertime); + cl->undertime =PSCHED_PASTPERFECT ; cl->avgidle = cl->maxidle; cl->deficit = cl->quantum; cl->cpriority = cl->priority;
@@ -1650,7 +1649,7 @@ cbq_dump_class_stats(struct Qdisc *sch, unsigned long arg, cl->xstats.avgidle = cl->avgidle; cl->xstats.undertime =0 ; -if (!PSCHED_IS_PASTPERFECT (cl->undertime)) +if (cl->undertime !=PSCHED_PASTPERFECT ) cl->xstats.undertime =PSCHED_TDIFF (cl->undertime, q->now); if (gnet_stats_copy_basic(d, &cl->bstats) < 0 ||
net/sched/sch_netem.c +1 -1
@@ -532,7 +532,7 @@ static int tfifo_init(struct Qdisc *sch, struct rtattr *opt) }else q->limit =max_t (u32, sch->dev->tx_queue_len,1 ); -PSCHED_SET_PASTPERFECT (q->oldest); + q->oldest =PSCHED_PASTPERFECT ;return 0 ; }
PATCH 6/11 : kill PSCHED_TDIFF
In reply to Patrick McHardy[NET_SCHED]: kill PSCHED_TDIFF
---
commit d72d57707edf96c31e62da0841faf59c011dcd92
tree 8b6192c94e025fb8b6e1be3b02526d4792bd4fa1
parent ec252ac5640ea38d3630cdb97333c398a75391b9
author Patrick McHardy <[email protected]> Fri, 23 Mar 2007 00:01:47 +0100 committer Patrick McHardy <[email protected]> Fri, 23 Mar 2007 10:31:29 +0100
include/net/pkt_sched.h | 1 - net/sched/sch_cbq.c | 14 +++++++------- 2 files changed, 7 insertions(+), 8 deletions(-)
include/net/pkt_sched.h +0 -1
@@ -51,7 +51,6 @@ typedef long psched_tdiff_t;#define PSCHED_GET_TIME (stamp) \ ((stamp) = PSCHED_NS2US(ktime_to_ns(ktime_get()))) -#define PSCHED_TDIFF (tv1, tv2) (long)((tv1) - (tv2))#define PSCHED_TDIFF_SAFE (tv1, tv2, bound) \ min_t(long long, (tv1) - (tv2), bound)#define PSCHED_PASTPERFECT 0
net/sched/sch_cbq.c +7 -7
@@ -386,7 +386,7 @@ cbq_mark_toplevel(struct cbq_sched_data *q, struct cbq_class *cl)psched_tdiff_t incr;PSCHED_GET_TIME (now); - incr =PSCHED_TDIFF (now, q->now_rt); + incr = now - q->now_rt; now = q->now + incr; do {
@@ -474,7 +474,7 @@ cbq_requeue(struct sk_buff *skb, struct Qdisc *sch)static void cbq_ovl_classic (struct cbq_class *cl) {struct cbq_sched_data *q =qdisc_priv (cl->qdisc); -psched_tdiff_t delay =PSCHED_TDIFF (cl->undertime, q->now); +psched_tdiff_t delay = cl->undertime - q->now;if (!cl->delayed) { delay += cl->offtime;
@@ -509,7 +509,7 @@ static void cbq_ovl_classic(struct cbq_class *cl)psched_tdiff_t base_delay = q->wd_expires;for (b = cl->borrow; b; b = b->borrow) { - delay =PSCHED_TDIFF (b->undertime, q->now); + delay = b->undertime - q->now;if (delay < base_delay) {if (delay <=0 ) delay =1 ;
@@ -547,7 +547,7 @@ static void cbq_ovl_rclassic(struct cbq_class *cl)static void cbq_ovl_delay (struct cbq_class *cl) {struct cbq_sched_data *q =qdisc_priv (cl->qdisc); -psched_tdiff_t delay =PSCHED_TDIFF (cl->undertime, q->now); +psched_tdiff_t delay = cl->undertime - q->now;if (!cl->delayed) {psched_time_t sched = q->now;
@@ -776,7 +776,7 @@ cbq_update(struct cbq_sched_data *q)idle = (now - last) - last_pktlen/rate */ - idle =PSCHED_TDIFF (q->now, cl->last); + idle = q->now - cl->last;if ((unsigned long )idle >128 *1024 *1024 ) { avgidle = cl->maxidle; }else {
@@ -1004,7 +1004,7 @@ cbq_dequeue(struct Qdisc *sch)psched_tdiff_t incr;PSCHED_GET_TIME (now); - incr =PSCHED_TDIFF (now, q->now_rt); + incr = now - q->now_rt;if (q->tx_class) {psched_tdiff_t incr2;
@@ -1650,7 +1650,7 @@ cbq_dump_class_stats(struct Qdisc *sch, unsigned long arg, cl->xstats.undertime =0 ;if (cl->undertime !=PSCHED_PASTPERFECT ) - cl->xstats.undertime =PSCHED_TDIFF (cl->undertime, q->now); + cl->xstats.undertime = cl->undertime - q->now; if (gnet_stats_copy_basic(d, &cl->bstats) < 0 ||#ifdef CONFIG_NET_ESTIMATOR
PATCH 7/11 : turn PSCHED_TDIFF_SAFE into inline function
In reply to Patrick McHardy[NET_SCHED]: turn PSCHED_TDIFF_SAFE into inline function
Also rename to psched_tdiff_bounded.
---
commit c86b236046f7de4094ceb2b2cb069c32969ee36c
tree 27c99a0d619bcabf384838adeae3c0469472b86b
parent d72d57707edf96c31e62da0841faf59c011dcd92
author Patrick McHardy <[email protected]> Fri, 23 Mar 2007 00:01:59 +0100 committer Patrick McHardy <[email protected]> Fri, 23 Mar 2007 10:31:30 +0100
include/net/pkt_sched.h | 8 ++++++-- include/net/red.h | 2 +- net/sched/act_police.c | 8 ++++---- net/sched/sch_htb.c | 4 ++-- net/sched/sch_tbf.c | 2 +- 5 files changed, 14 insertions(+), 10 deletions(-)
include/net/pkt_sched.h +6 -2
@@ -51,10 +51,14 @@ typedef long psched_tdiff_t;#define PSCHED_GET_TIME (stamp) \ ((stamp) = PSCHED_NS2US(ktime_to_ns(ktime_get()))) -#define PSCHED_TDIFF_SAFE (tv1, tv2, bound) \ - min_t(long long, (tv1) - (tv2), bound)#define PSCHED_PASTPERFECT 0 +static inline psched_tdiff_t +psched_tdiff_bounded (psched_time_t tv1,psched_time_t tv2,psched_time_t bound) +{ +return min (tv1 - tv2, bound); +} +struct qdisc_watchdog {struct hrtimer timer;struct Qdisc *qdisc;
include/net/red.h +1 -1
@@ -178,7 +178,7 @@ static inline unsigned long red_calc_qavg_from_idle_time(struct red_parms *p)int shift;PSCHED_GET_TIME (now); - us_idle =PSCHED_TDIFF_SAFE (now, p->qidlestart, p->Scell_max); + us_idle =psched_tdiff_bounded (now, p->qidlestart, p->Scell_max);/* * The problem: ideally, average length queue recalcultion should
net/sched/act_police.c +4 -4
@@ -298,8 +298,8 @@ static int tcf_act_police(struct sk_buff *skb, struct tc_action *a,PSCHED_GET_TIME (now); - toks =PSCHED_TDIFF_SAFE (now, police->tcfp_t_c, - police->tcfp_burst); + toks =psched_tdiff_bounded (now, police->tcfp_t_c, + police->tcfp_burst);if (police->tcfp_P_tab) { ptoks = toks + police->tcfp_ptoks;if (ptoks > (long )L2T_P (police, police->tcfp_mtu))
@@ -544,8 +544,8 @@ int tcf_police(struct sk_buff *skb, struct tcf_police *police) }PSCHED_GET_TIME (now); - toks =PSCHED_TDIFF_SAFE (now, police->tcfp_t_c, - police->tcfp_burst); + toks =psched_tdiff_bounded (now, police->tcfp_t_c, + police->tcfp_burst);if (police->tcfp_P_tab) { ptoks = toks + police->tcfp_ptoks;if (ptoks > (long )L2T_P (police, police->tcfp_mtu))
net/sched/sch_htb.c +2 -2
@@ -729,7 +729,7 @@ static void htb_charge_class(struct htb_sched *q, struct htb_class *cl, cl->T = tokswhile (cl) { - diff =PSCHED_TDIFF_SAFE (q->now, cl->t_c, (u32 ) cl->mbuffer); + diff =psched_tdiff_bounded (q->now, cl->t_c, cl->mbuffer);if (cl->level >= level) {if (cl->level == level) cl->xstats.lends++;
@@ -789,7 +789,7 @@ static psched_time_t htb_do_events(struct htb_sched *q, int level)return cl->pq_key;htb_safe_rb_erase (p, q->wait_pq + level); - diff =PSCHED_TDIFF_SAFE (q->now, cl->t_c, (u32 ) cl->mbuffer); + diff =psched_tdiff_bounded (q->now, cl->t_c, cl->mbuffer);htb_change_class_mode (q, cl, &diff);if (cl->cmode !=HTB_CAN_SEND )htb_add_to_wait_tree (q, cl, diff);
net/sched/sch_tbf.c +1 -1
@@ -201,7 +201,7 @@ static struct sk_buff *tbf_dequeue(struct Qdisc* sch)PSCHED_GET_TIME (now); - toks =PSCHED_TDIFF_SAFE (now, q->t_c, q->buffer); + toks =psched_tdiff_bounded (now, q->t_c, q->buffer);if (q->P_tab) { ptoks = toks + q->ptokens;
PATCH 8/11 : turn PSCHED_GET_TIME into inline function
In reply to Patrick McHardy[NET_SCHED]: turn PSCHED_GET_TIME into inline function
---
commit 231788aa3b9eef85b72ecac2e33441bd842ce3f4
tree f302e509ec32a86bc9a6c3712d188fc91455a213
parent c86b236046f7de4094ceb2b2cb069c32969ee36c
author Patrick McHardy <[email protected]> Fri, 23 Mar 2007 00:02:12 +0100 committer Patrick McHardy <[email protected]> Fri, 23 Mar 2007 10:31:30 +0100
include/net/pkt_sched.h | 8 +++++--- include/net/red.h | 4 ++-- net/sched/act_police.c | 9 ++++----- net/sched/sch_cbq.c | 10 +++++----- net/sched/sch_hfsc.c | 10 ++++------ net/sched/sch_htb.c | 6 +++--- net/sched/sch_netem.c | 8 +++----- net/sched/sch_tbf.c | 7 +++---- 8 files changed, 29 insertions(+), 33 deletions(-)
include/net/pkt_sched.h +5 -3
@@ -48,11 +48,13 @@ typedef long psched_tdiff_t;#define PSCHED_NS2US (x) ((x) >> 10)#define PSCHED_TICKS_PER_SEC PSCHED_NS2US(NSEC_PER_SEC) -#define PSCHED_GET_TIME (stamp) \ - ((stamp) = PSCHED_NS2US(ktime_to_ns(ktime_get()))) -#define PSCHED_PASTPERFECT 0 +static inline psched_time_t psched_get_time (void ) +{ +return PSCHED_NS2US (ktime_to_ns (ktime_get ())); +} +static inline psched_tdiff_t psched_tdiff_bounded (psched_time_t tv1,psched_time_t tv2,psched_time_t bound) {
include/net/red.h +2 -2
@@ -156,7 +156,7 @@ static inline int red_is_idling(struct red_parms *p)static inline void red_start_of_idle_period (struct red_parms *p) { -PSCHED_GET_TIME (p->qidlestart); + p->qidlestart =psched_get_time (); }static inline void red_end_of_idle_period (struct red_parms *p)
@@ -177,7 +177,7 @@ static inline unsigned long red_calc_qavg_from_idle_time(struct red_parms *p)long us_idle;int shift; -PSCHED_GET_TIME (now); + now =psched_get_time (); us_idle =psched_tdiff_bounded (now, p->qidlestart, p->Scell_max);/*
net/sched/act_police.c +4 -5
@@ -241,7 +241,7 @@ override:if (ret !=ACT_P_CREATED )return ret; -PSCHED_GET_TIME (police->tcfp_t_c); + police->tcfp_t_c =psched_get_time (); police->tcf_index = parm->index ? parm->index :tcf_hash_new_index (&police_idx_gen, &police_hash_info); h =tcf_hash (police->tcf_index,POL_TAB_MASK );
@@ -296,8 +296,7 @@ static int tcf_act_police(struct sk_buff *skb, struct tc_action *a,return police->tcfp_result; } -PSCHED_GET_TIME (now); - + now =psched_get_time (); toks =psched_tdiff_bounded (now, police->tcfp_t_c, police->tcfp_burst);if (police->tcfp_P_tab) {
@@ -495,7 +494,7 @@ struct tcf_police *tcf_police_locate(struct rtattr *rta, struct rtattr *est) }if (police->tcfp_P_tab) police->tcfp_ptoks =L2T_P (police, police->tcfp_mtu); -PSCHED_GET_TIME (police->tcfp_t_c); + police->tcfp_t_c =psched_get_time (); police->tcf_index = parm->index ? parm->index :tcf_police_new_index (); police->tcf_action = parm->action;
@@ -543,7 +542,7 @@ int tcf_police(struct sk_buff *skb, struct tcf_police *police)return police->tcfp_result; } -PSCHED_GET_TIME (now); + now =psched_get_time (); toks =psched_tdiff_bounded (now, police->tcfp_t_c, police->tcfp_burst);if (police->tcfp_P_tab) {
net/sched/sch_cbq.c +5 -5
@@ -385,7 +385,7 @@ cbq_mark_toplevel(struct cbq_sched_data *q, struct cbq_class *cl)psched_time_t now;psched_tdiff_t incr; -PSCHED_GET_TIME (now); + now =psched_get_time (); incr = now - q->now_rt; now = q->now + incr;
@@ -654,7 +654,7 @@ static enum hrtimer_restart cbq_undelay(struct hrtimer *timer)psched_tdiff_t delay =0 ;unsigned pmask; -PSCHED_GET_TIME (now); + now =psched_get_time (); pmask = q->pmask; q->pmask =0 ;
@@ -1003,7 +1003,7 @@ cbq_dequeue(struct Qdisc *sch)psched_time_t now;psched_tdiff_t incr; -PSCHED_GET_TIME (now); + now =psched_get_time (); incr = now - q->now_rt;if (q->tx_class) {
@@ -1277,7 +1277,7 @@ cbq_reset(struct Qdisc* sch)qdisc_watchdog_cancel (&q->watchdog);hrtimer_cancel (&q->delay_timer); q->toplevel =TC_CBQ_MAXLEVEL ; -PSCHED_GET_TIME (q->now); + q->now =psched_get_time (); q->now_rt = q->now;for (prio =0 ; prio <=TC_CBQ_MAXPRIO ; prio++)
@@ -1448,7 +1448,7 @@ static int cbq_init(struct Qdisc *sch, struct rtattr *opt)hrtimer_init (&q->delay_timer,CLOCK_MONOTONIC ,HRTIMER_MODE_ABS ); q->delay_timer.function = cbq_undelay; q->toplevel =TC_CBQ_MAXLEVEL ; -PSCHED_GET_TIME (q->now); + q->now =psched_get_time (); q->now_rt = q->now;cbq_link_class (&q->link);
net/sched/sch_hfsc.c +4 -6
@@ -629,9 +629,7 @@ rtsc_min(struct runtime_sc *rtsc, struct internal_sc *isc, u64 x, u64 y)static void init_ed (struct hfsc_class *cl,unsigned int next_len) { -u64 cur_time; - -PSCHED_GET_TIME (cur_time); +u64 cur_time =psched_get_time ();/* update the deadline curve */ rtsc_min (&cl->cl_deadline, &cl->cl_rsc, cur_time, cl->cl_cumul);
@@ -754,7 +752,7 @@ init_vf(struct hfsc_class *cl, unsigned int len)if (cl->cl_flags &HFSC_USC ) {/* class has upper limit curve */ if (cur_time ==0 ) -PSCHED_GET_TIME (cur_time); + cur_time =psched_get_time ();/* update the ulimit curve */ rtsc_min(&cl->cl_ulimit, &cl->cl_usc, cur_time,
@@ -1038,7 +1036,7 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,if (cl->cl_parent ==NULL && parentid !=TC_H_ROOT )return -EINVAL ; } -PSCHED_GET_TIME (cur_time); + cur_time =psched_get_time ();sch_tree_lock (sch);if (rsc !=NULL )
@@ -1637,7 +1635,7 @@ hfsc_dequeue(struct Qdisc *sch)if ((skb =__skb_dequeue (&q->requeue))) goto out; -PSCHED_GET_TIME (cur_time); + cur_time =psched_get_time ();/* * if there are eligible classes, use real-time criteria.
net/sched/sch_htb.c +3 -3
@@ -965,7 +965,7 @@ static struct sk_buff *htb_dequeue(struct Qdisc *sch)if (!sch->q.qlen) goto fin; -PSCHED_GET_TIME (q->now); + q->now =psched_get_time (); next_event = q->now +5 *PSCHED_TICKS_PER_SEC ; q->nwc_hit =0 ;
@@ -1274,7 +1274,7 @@ static void htb_parent_to_leaf(struct htb_class *cl, struct Qdisc *new_q) parent->un.leaf.prio = parent->prio; parent->tokens = parent->buffer; parent->ctokens = parent->cbuffer; -PSCHED_GET_TIME (parent->t_c); + parent->t_c =psched_get_time (); parent->cmode =HTB_CAN_SEND ; }
@@ -1471,7 +1471,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid, cl->tokens = hopt->buffer; cl->ctokens = hopt->cbuffer; cl->mbuffer =60 *PSCHED_TICKS_PER_SEC ;/* 1min */ -PSCHED_GET_TIME (cl->t_c); + cl->t_c =psched_get_time (); cl->cmode =HTB_CAN_SEND ;/* attach to the hash list and parent's family */
net/sched/sch_netem.c +3 -5
@@ -217,7 +217,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) delay =tabledist (q->latency, q->jitter, &q->delay_cor, q->delay_dist); -PSCHED_GET_TIME (now); + now =psched_get_time (); cb->time_to_send = now + delay; ++q->counter; ret = q->qdisc->enqueue (skb, q->qdisc);
@@ -226,7 +226,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)* Do re-ordering by putting one out of N packets at the front * of the queue. */ -PSCHED_GET_TIME (cb->time_to_send); + cb->time_to_send =psched_get_time (); q->counter =0 ; ret = q->qdisc->ops->requeue (skb, q->qdisc); }
@@ -281,11 +281,9 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)if (skb) {const struct netem_skb_cb *cb = (const struct netem_skb_cb *)skb->cb; -psched_time_t now; +psched_time_t now =psched_get_time ();/* if more time remaining? */ -PSCHED_GET_TIME (now); -if (cb->time_to_send <= now) {pr_debug ("netem_dequeue: return skb=%p\n" , skb); sch->q.qlen--;
net/sched/sch_tbf.c +3 -4
@@ -199,8 +199,7 @@ static struct sk_buff *tbf_dequeue(struct Qdisc* sch)long ptoks =0 ;unsigned int len = skb->len; -PSCHED_GET_TIME (now); - + now =psched_get_time (); toks =psched_tdiff_bounded (now, q->t_c, q->buffer);if (q->P_tab) {
@@ -254,7 +253,7 @@ static void tbf_reset(struct Qdisc* sch)qdisc_reset (q->qdisc); sch->q.qlen =0 ; -PSCHED_GET_TIME (q->t_c); + q->t_c =psched_get_time (); q->tokens = q->buffer; q->ptokens = q->mtu;qdisc_watchdog_cancel (&q->watchdog);
@@ -364,7 +363,7 @@ static int tbf_init(struct Qdisc* sch, struct rtattr *opt)if (opt ==NULL )return -EINVAL ; -PSCHED_GET_TIME (q->t_c); + q->t_c =psched_get_time ();qdisc_watchdog_init (&q->watchdog, sch); q->qdisc = &noop_qdisc;
PATCH 9/11 : Unline tcf_destroy
In reply to Patrick McHardy[NET_SCHED]: Unline tcf_destroy
Uninline tcf_destroy and add a helper function to destroy an entire filter chain.
---
commit 8da4bcec7e54c8344c8fd77c72a61f24ce12cfc3
tree 7f36f4af8e9413637fb9b65501f281fd8a915da3
parent 231788aa3b9eef85b72ecac2e33441bd842ce3f4
author Patrick McHardy <[email protected]> Fri, 23 Mar 2007 10:31:31 +0100 committer Patrick McHardy <[email protected]> Fri, 23 Mar 2007 10:31:31 +0100
include/net/sch_generic.h | 10 ++-------- net/sched/sch_api.c | 18 ++++++++++++++++++ net/sched/sch_atm.c | 17 ++--------------- net/sched/sch_cbq.c | 14 ++------------ net/sched/sch_dsmark.c | 8 +------- net/sched/sch_hfsc.c | 13 +------------ net/sched/sch_htb.c | 14 ++------------ net/sched/sch_ingress.c | 7 +------ net/sched/sch_prio.c | 7 +------ 9 files changed, 30 insertions(+), 78 deletions(-)
include/net/sch_generic.h +2 -8
@@ -177,14 +177,8 @@ extern void qdisc_tree_decrease_qlen(struct Qdisc *qdisc, unsigned int n);extern struct Qdisc *qdisc_alloc (struct net_device *dev,struct Qdisc_ops *ops);extern struct Qdisc *qdisc_create_dflt (struct net_device *dev,struct Qdisc_ops *ops,u32 parentid); - -static inline void -tcf_destroy (struct tcf_proto *tp) -{ - tp->ops->destroy (tp); -module_put (tp->ops->owner); -kfree (tp); -} +extern void tcf_destroy (struct tcf_proto *tp); +extern void tcf_destroy_chain (struct tcf_proto *fl);static inline int __qdisc_enqueue_tail (struct sk_buff *skb,struct Qdisc *sch,struct sk_buff_head *list)
net/sched/sch_api.c +18 -0
@@ -1220,6 +1220,24 @@ reclassify:return -1 ; } +void tcf_destroy (struct tcf_proto *tp) +{ + tp->ops->destroy (tp); +module_put (tp->ops->owner); +kfree (tp); +} + +void tcf_destroy_chain (struct tcf_proto *fl) +{ +struct tcf_proto *tp; + +while ((tp = fl) !=NULL ) { + fl = tp->next; +tcf_destroy (tp); + } +} +EXPORT_SYMBOL (tcf_destroy_chain); +#ifdef CONFIG_PROC_FS static int psched_show (struct seq_file *seq,void *v) {
net/sched/sch_atm.c +2 -15
@@ -158,19 +158,6 @@ static unsigned long atm_tc_bind_filter(struct Qdisc *sch,return atm_tc_get (sch,classid); } - -static void destroy_filters (struct atm_flow_data *flow) -{ -struct tcf_proto *filter; - -while ((filter = flow->filter_list)) { -DPRINTK ("destroy_filters: destroying filter %p\n" ,filter); - flow->filter_list = filter->next; -tcf_destroy (filter); - } -} - -/* * atm_tc_put handles all destructions, including the ones that are explicitly * requested (atm_tc_destroy, etc.). The assumption here is that we never drop
@@ -195,7 +182,7 @@ static void atm_tc_put(struct Qdisc *sch, unsigned long cl) *prev = flow->next;DPRINTK ("atm_tc_put: qdisc %p\n" ,flow->q);qdisc_destroy (flow->q); -destroy_filters (flow); +tcf_destroy_chain (flow->filter_list);if (flow->sock) {DPRINTK ("atm_tc_put: f_count %d\n" ,file_count (flow->sock->file));
@@ -611,7 +598,7 @@ static void atm_tc_destroy(struct Qdisc *sch)DPRINTK ("atm_tc_destroy(sch %p,[qdisc %p])\n" ,sch,p);/* races ? */ while ((flow = p->flows)) { -destroy_filters (flow); +tcf_destroy_chain (flow->filter_list);if (flow->ref >1 )printk (KERN_ERR "atm_destroy: %p->ref = %d\n" ,flow, flow->ref);
net/sched/sch_cbq.c +2 -12
@@ -1717,23 +1717,13 @@ static unsigned long cbq_get(struct Qdisc *sch, u32 classid)return 0 ; } -static void cbq_destroy_filters (struct cbq_class *cl) -{ -struct tcf_proto *tp; - -while ((tp = cl->filter_list) !=NULL ) { - cl->filter_list = tp->next; -tcf_destroy (tp); - } -} -static void cbq_destroy_class (struct Qdisc *sch,struct cbq_class *cl) {struct cbq_sched_data *q =qdisc_priv (sch);BUG_TRAP (!cl->filters); -cbq_destroy_filters (cl); +tcf_destroy_chain (cl->filter_list);qdisc_destroy (cl->q);qdisc_put_rtab (cl->R_tab);#ifdef CONFIG_NET_ESTIMATOR
@@ -1760,7 +1750,7 @@ cbq_destroy(struct Qdisc* sch)*/ for (h =0 ; h <16 ; h++)for (cl = q->classes[h]; cl; cl = cl->next) -cbq_destroy_filters (cl); +tcf_destroy_chain (cl->filter_list);for (h =0 ; h <16 ; h++) {struct cbq_class *next;
net/sched/sch_dsmark.c +1 -7
@@ -412,16 +412,10 @@ static void dsmark_reset(struct Qdisc *sch)static void dsmark_destroy (struct Qdisc *sch) {struct dsmark_qdisc_data *p =PRIV (sch); -struct tcf_proto *tp;DPRINTK ("dsmark_destroy(sch %p,[qdisc %p])\n" , sch, p); -while (p->filter_list) { - tp = p->filter_list; - p->filter_list = tp->next; -tcf_destroy (tp); - } - +tcf_destroy_chain (p->filter_list);qdisc_destroy (p->q);kfree (p->mask); }
net/sched/sch_hfsc.c +1 -12
@@ -1122,22 +1122,11 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, }static void -hfsc_destroy_filters (struct tcf_proto **fl) -{ -struct tcf_proto *tp; - -while ((tp = *fl) !=NULL ) { - *fl = tp->next; -tcf_destroy (tp); - } -} - -static void hfsc_destroy_class (struct Qdisc *sch,struct hfsc_class *cl) {struct hfsc_sched *q =qdisc_priv (sch); -hfsc_destroy_filters (&cl->filter_list); +tcf_destroy_chain (cl->filter_list);qdisc_destroy (cl->qdisc);#ifdef CONFIG_NET_ESTIMATOR gen_kill_estimator (&cl->bstats, &cl->rate_est);
net/sched/sch_htb.c +2 -12
@@ -1236,16 +1236,6 @@ static unsigned long htb_get(struct Qdisc *sch, u32 classid)return (unsigned long )cl; } -static void htb_destroy_filters (struct tcf_proto **fl) -{ -struct tcf_proto *tp; - -while ((tp = *fl) !=NULL ) { - *fl = tp->next; -tcf_destroy (tp); - } -} -static inline int htb_parent_last_child (struct htb_class *cl) {if (!cl->parent)
@@ -1289,7 +1279,7 @@ static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)qdisc_put_rtab (cl->rate);qdisc_put_rtab (cl->ceil); -htb_destroy_filters (&cl->filter_list); +tcf_destroy_chain (cl->filter_list);while (!list_empty (&cl->children)) htb_destroy_class(sch, list_entry(cl->children.next,
@@ -1321,7 +1311,7 @@ static void htb_destroy(struct Qdisc *sch)and surprisingly it worked in 2.4. But it must precede it because filter need its target class alive to be able to call unbind_filter on it (without Oops). */ -htb_destroy_filters (&q->filter_list); +tcf_destroy_chain (q->filter_list);while (!list_empty (&q->root)) htb_destroy_class(sch, list_entry(q->root.next,
net/sched/sch_ingress.c +1 -6
@@ -346,14 +346,9 @@ static void ingress_reset(struct Qdisc *sch)static void ingress_destroy (struct Qdisc *sch) {struct ingress_qdisc_data *p =PRIV (sch); -struct tcf_proto *tp;DPRINTK ("ingress_destroy(sch %p,[qdisc %p])\n" , sch, p); -while (p->filter_list) { - tp = p->filter_list; - p->filter_list = tp->next; -tcf_destroy (tp); - } +tcf_destroy_chain (p->filter_list);#if 0 /* for future use */ qdisc_destroy (p->q);
net/sched/sch_prio.c +1 -6
@@ -189,13 +189,8 @@ prio_destroy(struct Qdisc* sch) {int prio;struct prio_sched_data *q =qdisc_priv (sch); -struct tcf_proto *tp; - -while ((tp = q->filter_list) !=NULL ) { - q->filter_list = tp->next; -tcf_destroy (tp); - } +tcf_destroy_chain (q->filter_list);for (prio=0 ; prio<q->bands; prio++)qdisc_destroy (q->queues[prio]); }
PATCH 10/11 : qdisc: remove unnecessary memory barriers
In reply to Patrick McHardy[NET_SCHED]: qdisc: remove unnecessary memory barriers
We're holding dev->queue_lock in qdisc_watchdog_schedule and qdisc_watchdog_cancel, no need for the barriers.
---
commit e2459acd7dee06fb4d5e980f26c23d31db0e5de1
tree 47287fb285e9d920392863121e88e69e45779cbb
parent 8da4bcec7e54c8344c8fd77c72a61f24ce12cfc3
author Patrick McHardy <[email protected]> Fri, 23 Mar 2007 10:31:31 +0100 committer Patrick McHardy <[email protected]> Fri, 23 Mar 2007 10:31:31 +0100
net/sched/sch_api.c | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-)
net/sched/sch_api.c +0 -2
@@ -322,7 +322,6 @@ void qdisc_watchdog_schedule(struct qdisc_watchdog *wd, psched_time_t expires)ktime_t time; wd->qdisc->flags |=TCQ_F_THROTTLED ; -smp_wmb (); time =ktime_set (0 ,0 ); time =ktime_add_ns (time,PSCHED_US2NS (expires));hrtimer_start (&wd->timer, time,HRTIMER_MODE_ABS );
@@ -333,7 +332,6 @@ void qdisc_watchdog_cancel(struct qdisc_watchdog *wd) {hrtimer_cancel (&wd->timer); wd->qdisc->flags &= ~TCQ_F_THROTTLED ; -smp_wmb (); }EXPORT_SYMBOL (qdisc_watchdog_cancel);
PATCH 11/11 : qdisc: avoid dequeue while throttled
In reply to Patrick McHardy[NET_SCHED]: qdisc: avoid dequeue while throttled
Avoid dequeueing while the device is throttled.
---
commit 69f6039ded0bdaf93e3fc954140caae1e7fc9927
tree 9894ce3afc9f7e5cadb26269827ba4d4bca393fc
parent e2459acd7dee06fb4d5e980f26c23d31db0e5de1
author Patrick McHardy <[email protected]> Fri, 23 Mar 2007 10:31:32 +0100 committer Patrick McHardy <[email protected]> Fri, 23 Mar 2007 10:31:32 +0100
net/sched/sch_generic.c | 4 ++++ net/sched/sch_netem.c | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-)
net/sched/sch_generic.c +4 -0
@@ -93,6 +93,10 @@ static inline int qdisc_restart(struct net_device *dev)struct Qdisc *q = dev->qdisc;struct sk_buff *skb; +smp_rmb (); +if (q->flags &TCQ_F_THROTTLED ) +return q->q.qlen; +/* Dequeue packet */ if (((skb = dev->gso_skb)) || ((skb = q->dequeue (q)))) {unsigned nolock = (dev->features &NETIF_F_LLTX );
net/sched/sch_netem.c +0 -4
@@ -273,10 +273,6 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)struct netem_sched_data *q =qdisc_priv (sch);struct sk_buff *skb; -smp_mb (); -if (sch->flags &TCQ_F_THROTTLED ) -return NULL ; - skb = q->qdisc->dequeue (q->qdisc);if (skb) {const struct netem_skb_cb *cb
Re: [NET_SCHED 11/11]: qdisc: avoid dequeue while throttled
Quoted 1 line · Patrick McHardy
[
NET_SCHED]: qdisc: avoid dequeue while throttled
It just occured to me that this doesn't work properly with qdiscs that have multiple classes since they all don't properly maintain the TCQ_F_THROTTLED flag. They set it on dequeue when no active class is willing to give out packets, but when enqueueing to a non-active class (thereby activating it) it is still set even though we don't know if that class could be dequeued.
So this updated patch unsets the TCQ_F_THROTTLED flag whenever we activate a class. Additionally it removes the unsetting of TCQ_F_THROTTLED on successful dequeue since we're now guaranteed that it was not set before.
[NET_SCHED]: qdisc: avoid dequeue while throttled
Avoid dequeueing while the device is throttled.
---
commit 073456c84a46736a3aa1ae4cc9d953a9e97b327c
tree 805a29224001180c88a429e65812b97a489c427a
parent e2459acd7dee06fb4d5e980f26c23d31db0e5de1
author Patrick McHardy <[email protected]> Fri, 23 Mar 2007 15:37:51 +0100 committer Patrick McHardy <[email protected]> Fri, 23 Mar 2007 15:37:51 +0100
net/sched/sch_cbq.c | 5 +++-- net/sched/sch_generic.c | 4 ++++ net/sched/sch_hfsc.c | 5 +++-- net/sched/sch_htb.c | 6 ++++-- net/sched/sch_netem.c | 4 ---- net/sched/sch_tbf.c | 1 - 6 files changed, 14 insertions(+), 11 deletions(-)
net/sched/sch_cbq.c +3 -2
@@ -424,8 +424,10 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch) sch->bstats.packets++; sch->bstats.bytes+=len;cbq_mark_toplevel (q, cl); -if (!cl->next_alive) +if (!cl->next_alive) {cbq_activate_class (cl); + sch->flags &= ~TCQ_F_THROTTLED ; + }return ret; }
@@ -1030,7 +1032,6 @@ cbq_dequeue(struct Qdisc *sch) skb =cbq_dequeue_1 (sch);if (skb) { sch->q.qlen--; - sch->flags &= ~TCQ_F_THROTTLED ;return skb; }
net/sched/sch_generic.c +4 -0
@@ -93,6 +93,10 @@ static inline int qdisc_restart(struct net_device *dev)struct Qdisc *q = dev->qdisc;struct sk_buff *skb; +smp_rmb (); +if (q->flags &TCQ_F_THROTTLED ) +return q->q.qlen; +/* Dequeue packet */ if (((skb = dev->gso_skb)) || ((skb = q->dequeue (q)))) {unsigned nolock = (dev->features &NETIF_F_LLTX );
net/sched/sch_hfsc.c +3 -2
@@ -1597,8 +1597,10 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch)return err; } -if (cl->qdisc->q.qlen ==1 ) +if (cl->qdisc->q.qlen ==1 ) {set_active (cl, len); + sch->flags &= ~TCQ_F_THROTTLED ; + } cl->bstats.packets++; cl->bstats.bytes += len;
@@ -1672,7 +1674,6 @@ hfsc_dequeue(struct Qdisc *sch) } out: - sch->flags &= ~TCQ_F_THROTTLED ; sch->q.qlen--;return skb;
net/sched/sch_htb.c +4 -2
@@ -615,6 +615,8 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch)/* enqueue to helper queue */ if (q->direct_queue.qlen < q->direct_qlen) {__skb_queue_tail (&q->direct_queue, skb); +if (q->direct_queue.qlen ==1 ) + sch->flags &= ~TCQ_F_THROTTLED ; q->direct_pkts++; }else {kfree_skb (skb);
@@ -637,6 +639,8 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch) cl->bstats.packets++; cl->bstats.bytes += skb->len;htb_activate (q, cl); +if (cl->un.leaf.q->q.qlen ==1 ) + sch->flags &= ~TCQ_F_THROTTLED ; } sch->q.qlen++;
@@ -958,7 +962,6 @@ static struct sk_buff *htb_dequeue(struct Qdisc *sch)/* try to dequeue direct packets as high prio (!) to minimize cpu work */ skb =__skb_dequeue (&q->direct_queue);if (skb !=NULL ) { - sch->flags &= ~TCQ_F_THROTTLED ; sch->q.qlen--;return skb; }
@@ -991,7 +994,6 @@ static struct sk_buff *htb_dequeue(struct Qdisc *sch) skb =htb_dequeue_tree (q, prio, level);if (likely (skb !=NULL )) { sch->q.qlen--; - sch->flags &= ~TCQ_F_THROTTLED ; goto fin; } }
net/sched/sch_netem.c +0 -4
@@ -273,10 +273,6 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)struct netem_sched_data *q =qdisc_priv (sch);struct sk_buff *skb; -smp_mb (); -if (sch->flags &TCQ_F_THROTTLED ) -return NULL ; - skb = q->qdisc->dequeue (q->qdisc);if (skb) {const struct netem_skb_cb *cb
net/sched/sch_tbf.c +0 -1
@@ -218,7 +218,6 @@ static struct sk_buff *tbf_dequeue(struct Qdisc* sch) q->tokens = toks; q->ptokens = ptoks; sch->q.qlen--; - sch->flags &= ~TCQ_F_THROTTLED ;return skb; }
Re: [NET_SCHED 11/11]: qdisc: avoid dequeue while throttled
Quoted 10 lines · Patrick McHardy
Quoted 1 line
[
NET_SCHED]: qdisc: avoid dequeue while throttledIt just occured to me that this doesn't work properly with qdiscs that have multiple classes since they all don't properly maintain the
TCQ_F_THROTTLEDflag. They set it on dequeue when no active class is willing to give out packets, but when enqueueing to a non-active class (thereby activating it) it is still set even though we don't know if that class could be dequeued.
Quoted 4 lines
So this updated patch unsets the
TCQ_F_THROTTLEDflag whenever we activate a class. Additionally it removes the unsetting ofTCQ_F_THROTTLEDon successful dequeue since we're now guaranteed that it was not set before.
I found another case that doesn't work properly, so let me retract this patch until I've properly thought this through.
David Miller
maintainerRe: [NET_SCHED 11/11]: qdisc: avoid dequeue while throttled
From: Patrick McHardy <[email protected]>
Date: Fri, 23 Mar 2007 15:57:08 +0100
Quoted 2 lines
I found another case that doesn't work properly, so let me retract this patch until I've properly thought this through.
Ok, I'll apply the rest.
David Miller
maintainerFrom: Patrick McHardy <[email protected]>
Date: Fri, 23 Mar 2007 14:35:38 +0100 (MET)
Quoted 6 lines
These patches fix an off-by-one in netem, clean up
pkt_sched.hby removing most of the now unnecessary PSCHED time macros and turning the two remaining ones into inline functions, consolidate some common filter destruction code and move theTCQ_F_THROTTLEDoptimization from netem toqdisc_restart.Please apply, thanks.
Patches 1-10 applied.