diff options
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/Kconfig | 1 | ||||
-rw-r--r-- | net/sched/act_ipt.c | 10 | ||||
-rw-r--r-- | net/sched/cls_u32.c | 6 | ||||
-rw-r--r-- | net/sched/sch_atm.c | 1 | ||||
-rw-r--r-- | net/sched/sch_dsmark.c | 1 | ||||
-rw-r--r-- | net/sched/sch_generic.c | 2 | ||||
-rw-r--r-- | net/sched/sch_netem.c | 4 | ||||
-rw-r--r-- | net/sched/sch_prio.c | 2 | ||||
-rw-r--r-- | net/sched/sch_red.c | 179 | ||||
-rw-r--r-- | net/sched/sch_sfq.c | 5 | ||||
-rw-r--r-- | net/sched/sch_tbf.c | 9 |
11 files changed, 187 insertions, 33 deletions
diff --git a/net/sched/Kconfig b/net/sched/Kconfig index 778b1e5a4b50..13eeee582886 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig | |||
@@ -434,7 +434,6 @@ config NET_EMATCH_TEXT | |||
434 | 434 | ||
435 | config NET_CLS_ACT | 435 | config NET_CLS_ACT |
436 | bool "Actions" | 436 | bool "Actions" |
437 | depends on EXPERIMENTAL | ||
438 | select NET_ESTIMATOR | 437 | select NET_ESTIMATOR |
439 | ---help--- | 438 | ---help--- |
440 | Say Y here if you want to use traffic control actions. Actions | 439 | Say Y here if you want to use traffic control actions. Actions |
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index 39a22a3ffe78..6056d20ef429 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c | |||
@@ -70,7 +70,8 @@ ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook) | |||
70 | t->u.kernel.target = target; | 70 | t->u.kernel.target = target; |
71 | 71 | ||
72 | if (t->u.kernel.target->checkentry | 72 | if (t->u.kernel.target->checkentry |
73 | && !t->u.kernel.target->checkentry(table, NULL, t->data, | 73 | && !t->u.kernel.target->checkentry(table, NULL, |
74 | t->u.kernel.target, t->data, | ||
74 | t->u.target_size - sizeof(*t), | 75 | t->u.target_size - sizeof(*t), |
75 | hook)) { | 76 | hook)) { |
76 | DPRINTK("ipt_init_target: check failed for `%s'.\n", | 77 | DPRINTK("ipt_init_target: check failed for `%s'.\n", |
@@ -86,7 +87,7 @@ static void | |||
86 | ipt_destroy_target(struct ipt_entry_target *t) | 87 | ipt_destroy_target(struct ipt_entry_target *t) |
87 | { | 88 | { |
88 | if (t->u.kernel.target->destroy) | 89 | if (t->u.kernel.target->destroy) |
89 | t->u.kernel.target->destroy(t->data, | 90 | t->u.kernel.target->destroy(t->u.kernel.target, t->data, |
90 | t->u.target_size - sizeof(*t)); | 91 | t->u.target_size - sizeof(*t)); |
91 | module_put(t->u.kernel.target->me); | 92 | module_put(t->u.kernel.target->me); |
92 | } | 93 | } |
@@ -224,8 +225,9 @@ tcf_ipt(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res) | |||
224 | /* iptables targets take a double skb pointer in case the skb | 225 | /* iptables targets take a double skb pointer in case the skb |
225 | * needs to be replaced. We don't own the skb, so this must not | 226 | * needs to be replaced. We don't own the skb, so this must not |
226 | * happen. The pskb_expand_head above should make sure of this */ | 227 | * happen. The pskb_expand_head above should make sure of this */ |
227 | ret = p->t->u.kernel.target->target(&skb, skb->dev, NULL, | 228 | ret = p->t->u.kernel.target->target(&skb, skb->dev, NULL, p->hook, |
228 | p->hook, p->t->data, NULL); | 229 | p->t->u.kernel.target, p->t->data, |
230 | NULL); | ||
229 | switch (ret) { | 231 | switch (ret) { |
230 | case NF_ACCEPT: | 232 | case NF_ACCEPT: |
231 | result = TC_ACT_OK; | 233 | result = TC_ACT_OK; |
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 2b670479dde1..78e052591fa9 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c | |||
@@ -347,8 +347,7 @@ static int u32_destroy_key(struct tcf_proto *tp, struct tc_u_knode *n) | |||
347 | if (n->ht_down) | 347 | if (n->ht_down) |
348 | n->ht_down->refcnt--; | 348 | n->ht_down->refcnt--; |
349 | #ifdef CONFIG_CLS_U32_PERF | 349 | #ifdef CONFIG_CLS_U32_PERF |
350 | if (n) | 350 | kfree(n->pf); |
351 | kfree(n->pf); | ||
352 | #endif | 351 | #endif |
353 | kfree(n); | 352 | kfree(n); |
354 | return 0; | 353 | return 0; |
@@ -680,8 +679,7 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle, | |||
680 | return 0; | 679 | return 0; |
681 | } | 680 | } |
682 | #ifdef CONFIG_CLS_U32_PERF | 681 | #ifdef CONFIG_CLS_U32_PERF |
683 | if (n) | 682 | kfree(n->pf); |
684 | kfree(n->pf); | ||
685 | #endif | 683 | #endif |
686 | kfree(n); | 684 | kfree(n); |
687 | return err; | 685 | return err; |
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index 93ebce40acac..ac7cb60d1e25 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c | |||
@@ -638,6 +638,7 @@ static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl, | |||
638 | sch,p,flow,skb,tcm); | 638 | sch,p,flow,skb,tcm); |
639 | if (!find_flow(p,flow)) return -EINVAL; | 639 | if (!find_flow(p,flow)) return -EINVAL; |
640 | tcm->tcm_handle = flow->classid; | 640 | tcm->tcm_handle = flow->classid; |
641 | tcm->tcm_info = flow->q->handle; | ||
641 | rta = (struct rtattr *) b; | 642 | rta = (struct rtattr *) b; |
642 | RTA_PUT(skb,TCA_OPTIONS,0,NULL); | 643 | RTA_PUT(skb,TCA_OPTIONS,0,NULL); |
643 | RTA_PUT(skb,TCA_ATM_HDR,flow->hdr_len,flow->hdr); | 644 | RTA_PUT(skb,TCA_ATM_HDR,flow->hdr_len,flow->hdr); |
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c index 13e0e7b3856b..f6320ca70493 100644 --- a/net/sched/sch_dsmark.c +++ b/net/sched/sch_dsmark.c | |||
@@ -438,6 +438,7 @@ static int dsmark_dump_class(struct Qdisc *sch, unsigned long cl, | |||
438 | return -EINVAL; | 438 | return -EINVAL; |
439 | 439 | ||
440 | tcm->tcm_handle = TC_H_MAKE(TC_H_MAJ(sch->handle), cl-1); | 440 | tcm->tcm_handle = TC_H_MAKE(TC_H_MAJ(sch->handle), cl-1); |
441 | tcm->tcm_info = p->q->handle; | ||
441 | 442 | ||
442 | opts = RTA_NEST(skb, TCA_OPTIONS); | 443 | opts = RTA_NEST(skb, TCA_OPTIONS); |
443 | RTA_PUT_U8(skb,TCA_DSMARK_MASK, p->mask[cl-1]); | 444 | RTA_PUT_U8(skb,TCA_DSMARK_MASK, p->mask[cl-1]); |
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 99ceb91f0150..31eb83717c26 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -234,7 +234,7 @@ static void dev_watchdog_down(struct net_device *dev) | |||
234 | { | 234 | { |
235 | spin_lock_bh(&dev->xmit_lock); | 235 | spin_lock_bh(&dev->xmit_lock); |
236 | if (del_timer(&dev->watchdog_timer)) | 236 | if (del_timer(&dev->watchdog_timer)) |
237 | __dev_put(dev); | 237 | dev_put(dev); |
238 | spin_unlock_bh(&dev->xmit_lock); | 238 | spin_unlock_bh(&dev->xmit_lock); |
239 | } | 239 | } |
240 | 240 | ||
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index ba5283204837..7228d30512c7 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c | |||
@@ -252,9 +252,9 @@ static int netem_requeue(struct sk_buff *skb, struct Qdisc *sch) | |||
252 | static unsigned int netem_drop(struct Qdisc* sch) | 252 | static unsigned int netem_drop(struct Qdisc* sch) |
253 | { | 253 | { |
254 | struct netem_sched_data *q = qdisc_priv(sch); | 254 | struct netem_sched_data *q = qdisc_priv(sch); |
255 | unsigned int len; | 255 | unsigned int len = 0; |
256 | 256 | ||
257 | if ((len = q->qdisc->ops->drop(q->qdisc)) != 0) { | 257 | if (q->qdisc->ops->drop && (len = q->qdisc->ops->drop(q->qdisc)) != 0) { |
258 | sch->q.qlen--; | 258 | sch->q.qlen--; |
259 | sch->qstats.drops++; | 259 | sch->qstats.drops++; |
260 | } | 260 | } |
diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index 1641db33a994..3395ca7bcadf 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c | |||
@@ -165,7 +165,7 @@ static unsigned int prio_drop(struct Qdisc* sch) | |||
165 | 165 | ||
166 | for (prio = q->bands-1; prio >= 0; prio--) { | 166 | for (prio = q->bands-1; prio >= 0; prio--) { |
167 | qdisc = q->queues[prio]; | 167 | qdisc = q->queues[prio]; |
168 | if ((len = qdisc->ops->drop(qdisc)) != 0) { | 168 | if (qdisc->ops->drop && (len = qdisc->ops->drop(qdisc)) != 0) { |
169 | sch->q.qlen--; | 169 | sch->q.qlen--; |
170 | return len; | 170 | return len; |
171 | } | 171 | } |
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index dccfa44c2d71..2be563cba72b 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c | |||
@@ -44,6 +44,7 @@ struct red_sched_data | |||
44 | unsigned char flags; | 44 | unsigned char flags; |
45 | struct red_parms parms; | 45 | struct red_parms parms; |
46 | struct red_stats stats; | 46 | struct red_stats stats; |
47 | struct Qdisc *qdisc; | ||
47 | }; | 48 | }; |
48 | 49 | ||
49 | static inline int red_use_ecn(struct red_sched_data *q) | 50 | static inline int red_use_ecn(struct red_sched_data *q) |
@@ -59,8 +60,10 @@ static inline int red_use_harddrop(struct red_sched_data *q) | |||
59 | static int red_enqueue(struct sk_buff *skb, struct Qdisc* sch) | 60 | static int red_enqueue(struct sk_buff *skb, struct Qdisc* sch) |
60 | { | 61 | { |
61 | struct red_sched_data *q = qdisc_priv(sch); | 62 | struct red_sched_data *q = qdisc_priv(sch); |
63 | struct Qdisc *child = q->qdisc; | ||
64 | int ret; | ||
62 | 65 | ||
63 | q->parms.qavg = red_calc_qavg(&q->parms, sch->qstats.backlog); | 66 | q->parms.qavg = red_calc_qavg(&q->parms, child->qstats.backlog); |
64 | 67 | ||
65 | if (red_is_idling(&q->parms)) | 68 | if (red_is_idling(&q->parms)) |
66 | red_end_of_idle_period(&q->parms); | 69 | red_end_of_idle_period(&q->parms); |
@@ -91,11 +94,16 @@ static int red_enqueue(struct sk_buff *skb, struct Qdisc* sch) | |||
91 | break; | 94 | break; |
92 | } | 95 | } |
93 | 96 | ||
94 | if (sch->qstats.backlog + skb->len <= q->limit) | 97 | ret = child->enqueue(skb, child); |
95 | return qdisc_enqueue_tail(skb, sch); | 98 | if (likely(ret == NET_XMIT_SUCCESS)) { |
96 | 99 | sch->bstats.bytes += skb->len; | |
97 | q->stats.pdrop++; | 100 | sch->bstats.packets++; |
98 | return qdisc_drop(skb, sch); | 101 | sch->q.qlen++; |
102 | } else { | ||
103 | q->stats.pdrop++; | ||
104 | sch->qstats.drops++; | ||
105 | } | ||
106 | return ret; | ||
99 | 107 | ||
100 | congestion_drop: | 108 | congestion_drop: |
101 | qdisc_drop(skb, sch); | 109 | qdisc_drop(skb, sch); |
@@ -105,21 +113,30 @@ congestion_drop: | |||
105 | static int red_requeue(struct sk_buff *skb, struct Qdisc* sch) | 113 | static int red_requeue(struct sk_buff *skb, struct Qdisc* sch) |
106 | { | 114 | { |
107 | struct red_sched_data *q = qdisc_priv(sch); | 115 | struct red_sched_data *q = qdisc_priv(sch); |
116 | struct Qdisc *child = q->qdisc; | ||
117 | int ret; | ||
108 | 118 | ||
109 | if (red_is_idling(&q->parms)) | 119 | if (red_is_idling(&q->parms)) |
110 | red_end_of_idle_period(&q->parms); | 120 | red_end_of_idle_period(&q->parms); |
111 | 121 | ||
112 | return qdisc_requeue(skb, sch); | 122 | ret = child->ops->requeue(skb, child); |
123 | if (likely(ret == NET_XMIT_SUCCESS)) { | ||
124 | sch->qstats.requeues++; | ||
125 | sch->q.qlen++; | ||
126 | } | ||
127 | return ret; | ||
113 | } | 128 | } |
114 | 129 | ||
115 | static struct sk_buff * red_dequeue(struct Qdisc* sch) | 130 | static struct sk_buff * red_dequeue(struct Qdisc* sch) |
116 | { | 131 | { |
117 | struct sk_buff *skb; | 132 | struct sk_buff *skb; |
118 | struct red_sched_data *q = qdisc_priv(sch); | 133 | struct red_sched_data *q = qdisc_priv(sch); |
134 | struct Qdisc *child = q->qdisc; | ||
119 | 135 | ||
120 | skb = qdisc_dequeue_head(sch); | 136 | skb = child->dequeue(child); |
121 | 137 | if (skb) | |
122 | if (skb == NULL && !red_is_idling(&q->parms)) | 138 | sch->q.qlen--; |
139 | else if (!red_is_idling(&q->parms)) | ||
123 | red_start_of_idle_period(&q->parms); | 140 | red_start_of_idle_period(&q->parms); |
124 | 141 | ||
125 | return skb; | 142 | return skb; |
@@ -127,14 +144,14 @@ static struct sk_buff * red_dequeue(struct Qdisc* sch) | |||
127 | 144 | ||
128 | static unsigned int red_drop(struct Qdisc* sch) | 145 | static unsigned int red_drop(struct Qdisc* sch) |
129 | { | 146 | { |
130 | struct sk_buff *skb; | ||
131 | struct red_sched_data *q = qdisc_priv(sch); | 147 | struct red_sched_data *q = qdisc_priv(sch); |
148 | struct Qdisc *child = q->qdisc; | ||
149 | unsigned int len; | ||
132 | 150 | ||
133 | skb = qdisc_dequeue_tail(sch); | 151 | if (child->ops->drop && (len = child->ops->drop(child)) > 0) { |
134 | if (skb) { | ||
135 | unsigned int len = skb->len; | ||
136 | q->stats.other++; | 152 | q->stats.other++; |
137 | qdisc_drop(skb, sch); | 153 | sch->qstats.drops++; |
154 | sch->q.qlen--; | ||
138 | return len; | 155 | return len; |
139 | } | 156 | } |
140 | 157 | ||
@@ -148,15 +165,48 @@ static void red_reset(struct Qdisc* sch) | |||
148 | { | 165 | { |
149 | struct red_sched_data *q = qdisc_priv(sch); | 166 | struct red_sched_data *q = qdisc_priv(sch); |
150 | 167 | ||
151 | qdisc_reset_queue(sch); | 168 | qdisc_reset(q->qdisc); |
169 | sch->q.qlen = 0; | ||
152 | red_restart(&q->parms); | 170 | red_restart(&q->parms); |
153 | } | 171 | } |
154 | 172 | ||
173 | static void red_destroy(struct Qdisc *sch) | ||
174 | { | ||
175 | struct red_sched_data *q = qdisc_priv(sch); | ||
176 | qdisc_destroy(q->qdisc); | ||
177 | } | ||
178 | |||
179 | static struct Qdisc *red_create_dflt(struct net_device *dev, u32 limit) | ||
180 | { | ||
181 | struct Qdisc *q = qdisc_create_dflt(dev, &bfifo_qdisc_ops); | ||
182 | struct rtattr *rta; | ||
183 | int ret; | ||
184 | |||
185 | if (q) { | ||
186 | rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)), | ||
187 | GFP_KERNEL); | ||
188 | if (rta) { | ||
189 | rta->rta_type = RTM_NEWQDISC; | ||
190 | rta->rta_len = RTA_LENGTH(sizeof(struct tc_fifo_qopt)); | ||
191 | ((struct tc_fifo_qopt *)RTA_DATA(rta))->limit = limit; | ||
192 | |||
193 | ret = q->ops->change(q, rta); | ||
194 | kfree(rta); | ||
195 | |||
196 | if (ret == 0) | ||
197 | return q; | ||
198 | } | ||
199 | qdisc_destroy(q); | ||
200 | } | ||
201 | return NULL; | ||
202 | } | ||
203 | |||
155 | static int red_change(struct Qdisc *sch, struct rtattr *opt) | 204 | static int red_change(struct Qdisc *sch, struct rtattr *opt) |
156 | { | 205 | { |
157 | struct red_sched_data *q = qdisc_priv(sch); | 206 | struct red_sched_data *q = qdisc_priv(sch); |
158 | struct rtattr *tb[TCA_RED_MAX]; | 207 | struct rtattr *tb[TCA_RED_MAX]; |
159 | struct tc_red_qopt *ctl; | 208 | struct tc_red_qopt *ctl; |
209 | struct Qdisc *child = NULL; | ||
160 | 210 | ||
161 | if (opt == NULL || rtattr_parse_nested(tb, TCA_RED_MAX, opt)) | 211 | if (opt == NULL || rtattr_parse_nested(tb, TCA_RED_MAX, opt)) |
162 | return -EINVAL; | 212 | return -EINVAL; |
@@ -169,9 +219,17 @@ static int red_change(struct Qdisc *sch, struct rtattr *opt) | |||
169 | 219 | ||
170 | ctl = RTA_DATA(tb[TCA_RED_PARMS-1]); | 220 | ctl = RTA_DATA(tb[TCA_RED_PARMS-1]); |
171 | 221 | ||
222 | if (ctl->limit > 0) { | ||
223 | child = red_create_dflt(sch->dev, ctl->limit); | ||
224 | if (child == NULL) | ||
225 | return -ENOMEM; | ||
226 | } | ||
227 | |||
172 | sch_tree_lock(sch); | 228 | sch_tree_lock(sch); |
173 | q->flags = ctl->flags; | 229 | q->flags = ctl->flags; |
174 | q->limit = ctl->limit; | 230 | q->limit = ctl->limit; |
231 | if (child) | ||
232 | qdisc_destroy(xchg(&q->qdisc, child)); | ||
175 | 233 | ||
176 | red_set_parms(&q->parms, ctl->qth_min, ctl->qth_max, ctl->Wlog, | 234 | red_set_parms(&q->parms, ctl->qth_min, ctl->qth_max, ctl->Wlog, |
177 | ctl->Plog, ctl->Scell_log, | 235 | ctl->Plog, ctl->Scell_log, |
@@ -186,6 +244,9 @@ static int red_change(struct Qdisc *sch, struct rtattr *opt) | |||
186 | 244 | ||
187 | static int red_init(struct Qdisc* sch, struct rtattr *opt) | 245 | static int red_init(struct Qdisc* sch, struct rtattr *opt) |
188 | { | 246 | { |
247 | struct red_sched_data *q = qdisc_priv(sch); | ||
248 | |||
249 | q->qdisc = &noop_qdisc; | ||
189 | return red_change(sch, opt); | 250 | return red_change(sch, opt); |
190 | } | 251 | } |
191 | 252 | ||
@@ -224,15 +285,101 @@ static int red_dump_stats(struct Qdisc *sch, struct gnet_dump *d) | |||
224 | return gnet_stats_copy_app(d, &st, sizeof(st)); | 285 | return gnet_stats_copy_app(d, &st, sizeof(st)); |
225 | } | 286 | } |
226 | 287 | ||
288 | static int red_dump_class(struct Qdisc *sch, unsigned long cl, | ||
289 | struct sk_buff *skb, struct tcmsg *tcm) | ||
290 | { | ||
291 | struct red_sched_data *q = qdisc_priv(sch); | ||
292 | |||
293 | if (cl != 1) | ||
294 | return -ENOENT; | ||
295 | tcm->tcm_handle |= TC_H_MIN(1); | ||
296 | tcm->tcm_info = q->qdisc->handle; | ||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | static int red_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, | ||
301 | struct Qdisc **old) | ||
302 | { | ||
303 | struct red_sched_data *q = qdisc_priv(sch); | ||
304 | |||
305 | if (new == NULL) | ||
306 | new = &noop_qdisc; | ||
307 | |||
308 | sch_tree_lock(sch); | ||
309 | *old = xchg(&q->qdisc, new); | ||
310 | qdisc_reset(*old); | ||
311 | sch->q.qlen = 0; | ||
312 | sch_tree_unlock(sch); | ||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | static struct Qdisc *red_leaf(struct Qdisc *sch, unsigned long arg) | ||
317 | { | ||
318 | struct red_sched_data *q = qdisc_priv(sch); | ||
319 | return q->qdisc; | ||
320 | } | ||
321 | |||
322 | static unsigned long red_get(struct Qdisc *sch, u32 classid) | ||
323 | { | ||
324 | return 1; | ||
325 | } | ||
326 | |||
327 | static void red_put(struct Qdisc *sch, unsigned long arg) | ||
328 | { | ||
329 | return; | ||
330 | } | ||
331 | |||
332 | static int red_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | ||
333 | struct rtattr **tca, unsigned long *arg) | ||
334 | { | ||
335 | return -ENOSYS; | ||
336 | } | ||
337 | |||
338 | static int red_delete(struct Qdisc *sch, unsigned long cl) | ||
339 | { | ||
340 | return -ENOSYS; | ||
341 | } | ||
342 | |||
343 | static void red_walk(struct Qdisc *sch, struct qdisc_walker *walker) | ||
344 | { | ||
345 | if (!walker->stop) { | ||
346 | if (walker->count >= walker->skip) | ||
347 | if (walker->fn(sch, 1, walker) < 0) { | ||
348 | walker->stop = 1; | ||
349 | return; | ||
350 | } | ||
351 | walker->count++; | ||
352 | } | ||
353 | } | ||
354 | |||
355 | static struct tcf_proto **red_find_tcf(struct Qdisc *sch, unsigned long cl) | ||
356 | { | ||
357 | return NULL; | ||
358 | } | ||
359 | |||
360 | static struct Qdisc_class_ops red_class_ops = { | ||
361 | .graft = red_graft, | ||
362 | .leaf = red_leaf, | ||
363 | .get = red_get, | ||
364 | .put = red_put, | ||
365 | .change = red_change_class, | ||
366 | .delete = red_delete, | ||
367 | .walk = red_walk, | ||
368 | .tcf_chain = red_find_tcf, | ||
369 | .dump = red_dump_class, | ||
370 | }; | ||
371 | |||
227 | static struct Qdisc_ops red_qdisc_ops = { | 372 | static struct Qdisc_ops red_qdisc_ops = { |
228 | .id = "red", | 373 | .id = "red", |
229 | .priv_size = sizeof(struct red_sched_data), | 374 | .priv_size = sizeof(struct red_sched_data), |
375 | .cl_ops = &red_class_ops, | ||
230 | .enqueue = red_enqueue, | 376 | .enqueue = red_enqueue, |
231 | .dequeue = red_dequeue, | 377 | .dequeue = red_dequeue, |
232 | .requeue = red_requeue, | 378 | .requeue = red_requeue, |
233 | .drop = red_drop, | 379 | .drop = red_drop, |
234 | .init = red_init, | 380 | .init = red_init, |
235 | .reset = red_reset, | 381 | .reset = red_reset, |
382 | .destroy = red_destroy, | ||
236 | .change = red_change, | 383 | .change = red_change, |
237 | .dump = red_dump, | 384 | .dump = red_dump, |
238 | .dump_stats = red_dump_stats, | 385 | .dump_stats = red_dump_stats, |
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 86d8da0cbd02..e057768f68b4 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c | |||
@@ -232,6 +232,7 @@ static unsigned int sfq_drop(struct Qdisc *sch) | |||
232 | sfq_dec(q, x); | 232 | sfq_dec(q, x); |
233 | sch->q.qlen--; | 233 | sch->q.qlen--; |
234 | sch->qstats.drops++; | 234 | sch->qstats.drops++; |
235 | sch->qstats.backlog -= len; | ||
235 | return len; | 236 | return len; |
236 | } | 237 | } |
237 | 238 | ||
@@ -248,6 +249,7 @@ static unsigned int sfq_drop(struct Qdisc *sch) | |||
248 | sch->q.qlen--; | 249 | sch->q.qlen--; |
249 | q->ht[q->hash[d]] = SFQ_DEPTH; | 250 | q->ht[q->hash[d]] = SFQ_DEPTH; |
250 | sch->qstats.drops++; | 251 | sch->qstats.drops++; |
252 | sch->qstats.backlog -= len; | ||
251 | return len; | 253 | return len; |
252 | } | 254 | } |
253 | 255 | ||
@@ -266,6 +268,7 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc* sch) | |||
266 | q->ht[hash] = x = q->dep[SFQ_DEPTH].next; | 268 | q->ht[hash] = x = q->dep[SFQ_DEPTH].next; |
267 | q->hash[x] = hash; | 269 | q->hash[x] = hash; |
268 | } | 270 | } |
271 | sch->qstats.backlog += skb->len; | ||
269 | __skb_queue_tail(&q->qs[x], skb); | 272 | __skb_queue_tail(&q->qs[x], skb); |
270 | sfq_inc(q, x); | 273 | sfq_inc(q, x); |
271 | if (q->qs[x].qlen == 1) { /* The flow is new */ | 274 | if (q->qs[x].qlen == 1) { /* The flow is new */ |
@@ -301,6 +304,7 @@ sfq_requeue(struct sk_buff *skb, struct Qdisc* sch) | |||
301 | q->ht[hash] = x = q->dep[SFQ_DEPTH].next; | 304 | q->ht[hash] = x = q->dep[SFQ_DEPTH].next; |
302 | q->hash[x] = hash; | 305 | q->hash[x] = hash; |
303 | } | 306 | } |
307 | sch->qstats.backlog += skb->len; | ||
304 | __skb_queue_head(&q->qs[x], skb); | 308 | __skb_queue_head(&q->qs[x], skb); |
305 | sfq_inc(q, x); | 309 | sfq_inc(q, x); |
306 | if (q->qs[x].qlen == 1) { /* The flow is new */ | 310 | if (q->qs[x].qlen == 1) { /* The flow is new */ |
@@ -344,6 +348,7 @@ sfq_dequeue(struct Qdisc* sch) | |||
344 | skb = __skb_dequeue(&q->qs[a]); | 348 | skb = __skb_dequeue(&q->qs[a]); |
345 | sfq_dec(q, a); | 349 | sfq_dec(q, a); |
346 | sch->q.qlen--; | 350 | sch->q.qlen--; |
351 | sch->qstats.backlog -= skb->len; | ||
347 | 352 | ||
348 | /* Is the slot empty? */ | 353 | /* Is the slot empty? */ |
349 | if (q->qs[a].qlen == 0) { | 354 | if (q->qs[a].qlen == 0) { |
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index cb9711ea8c6c..d8e03c74ca76 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c | |||
@@ -177,9 +177,9 @@ static int tbf_requeue(struct sk_buff *skb, struct Qdisc* sch) | |||
177 | static unsigned int tbf_drop(struct Qdisc* sch) | 177 | static unsigned int tbf_drop(struct Qdisc* sch) |
178 | { | 178 | { |
179 | struct tbf_sched_data *q = qdisc_priv(sch); | 179 | struct tbf_sched_data *q = qdisc_priv(sch); |
180 | unsigned int len; | 180 | unsigned int len = 0; |
181 | 181 | ||
182 | if ((len = q->qdisc->ops->drop(q->qdisc)) != 0) { | 182 | if (q->qdisc->ops->drop && (len = q->qdisc->ops->drop(q->qdisc)) != 0) { |
183 | sch->q.qlen--; | 183 | sch->q.qlen--; |
184 | sch->qstats.drops++; | 184 | sch->qstats.drops++; |
185 | } | 185 | } |
@@ -341,13 +341,14 @@ static int tbf_change(struct Qdisc* sch, struct rtattr *opt) | |||
341 | if (max_size < 0) | 341 | if (max_size < 0) |
342 | goto done; | 342 | goto done; |
343 | 343 | ||
344 | if (q->qdisc == &noop_qdisc) { | 344 | if (qopt->limit > 0) { |
345 | if ((child = tbf_create_dflt_qdisc(sch->dev, qopt->limit)) == NULL) | 345 | if ((child = tbf_create_dflt_qdisc(sch->dev, qopt->limit)) == NULL) |
346 | goto done; | 346 | goto done; |
347 | } | 347 | } |
348 | 348 | ||
349 | sch_tree_lock(sch); | 349 | sch_tree_lock(sch); |
350 | if (child) q->qdisc = child; | 350 | if (child) |
351 | qdisc_destroy(xchg(&q->qdisc, child)); | ||
351 | q->limit = qopt->limit; | 352 | q->limit = qopt->limit; |
352 | q->mtu = qopt->mtu; | 353 | q->mtu = qopt->mtu; |
353 | q->max_size = max_size; | 354 | q->max_size = max_size; |